#include <windows.h>
#include <iostream>
using namespace std;const int MAX_LOADSTRING = 100;class CMyWin
{
public:
CMyWin(){};
virtual ~CMyWin(); ATOM MyRegisterClass(HINSTANCE hInstance);
bool InitInstance(HINSTANCE hInstance, int nCmdShow);
int RunMessage();
HINSTANCE GetAppInstance()
{
return m_hInstance;
}
protected:
static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
static INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);protected:
HINSTANCE m_hInstance;
HWND m_hWnd; TCHAR m_strWindowClass[MAX_LOADSTRING];
TCHAR m_strTitle[MAX_LOADSTRING];
};#include "MyWin.h"
#include "resource.h"
ATOM CMyWin::MyRegisterClass(HINSTANCE hInstance)
{
LoadString(hInstance, IDS_APPLATION, m_strWindowClass, MAX_LOADSTRING);
LoadString(hInstance, IDS_TITLE, m_strTitle, MAX_LOADSTRING); WNDCLASSEX wcex; wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_APPLICATION));
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = MAKEINTRESOURCE(IDR_MENU);
wcex.lpszClassName = m_strWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_APPLICATION)); return RegisterClassEx(&wcex);
}bool CMyWin::InitInstance(HINSTANCE hInstance, int nCmdShow)
{
m_hInstance = hInstance;

m_hWnd = CreateWindow(m_strWindowClass, m_strTitle, WS_OVERLAPPEDWINDOW,
      CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL); if(!m_hWnd)
return false; SetWindowLongPtr(m_hWnd, GWL_USERDATA, (LONG)(LONG_PTR)this); ShowWindow(m_hWnd, nCmdShow);
UpdateWindow(m_hWnd); return true;
}int CMyWin::RunMessage()
{
MSG msg;
BOOL bRet;
HACCEL hAccelTable = LoadAccelerators(m_hInstance, MAKEINTRESOURCE(IDR_ACCELERATOR));
while ( (bRet = GetMessage(&msg, NULL, 0, 0)) != 0)
{
if (bRet == -1)
{
//处理出错。 }
else if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
} return 0;
}LRESULT CALLBACK CMyWin::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
//获取窗口对应的类指针。
LONG_PTR plptrWin = GetWindowLongPtr(hWnd,GWLP_USERDATA);
if (plptrWin == NULL)
{
return DefWindowProc(hWnd, message, wParam, lParam);
} CMyWin* pWin = reinterpret_cast<CMyWin*>(plptrWin); int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;
HWND hBtn; switch (message)
{
case WM_COMMAND:
wmId    = LOWORD(wParam);
wmEvent = HIWORD(wParam);
// 菜单选项命令响应:
switch (wmId)
{
case IDM_ABOUT:
DialogBox(pWin->GetAppInstance(), MAKEINTRESOURCE(IDD_ABOUT), 
hWnd, CMyWin::About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break; case WM_CREATE:
hBtn = CreateWindow(TEXT("button"), TEXT("按钮"), WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, 50, 50, 50, 20, 
hWnd, (HMENU)1, pWin->GetAppInstance(), NULL);
for(;;)
break;
case WM_PAINT:
{
hdc = BeginPaint(hWnd, &ps);
//
std::wstring strShow(TEXT("C++窗口类的实现"));
TextOut(hdc,10,10,strShow.c_str(),(int)strShow.length()); // 
EndPaint(hWnd, &ps);
}
break;
case WM_DESTROY:
//设置窗口类指针为空。
SetWindowLongPtr(hWnd, GWL_USERDATA,NULL); PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}INT_PTR CALLBACK CMyWin::About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
UNREFERENCED_PARAMETER(lParam);
switch (message)
{
case WM_INITDIALOG:
return (INT_PTR)TRUE; case WM_COMMAND:
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
{
EndDialog(hDlg, LOWORD(wParam));
return (INT_PTR)TRUE;
}
break;
}
return (INT_PTR)FALSE;
}CMyWin::~CMyWin()
{}#include "MyWin.h"
int APIENTRY WinMain(HINSTANCE hInstance,
 HINSTANCE hPrevInstance,
 LPSTR lpCmdLine,
 int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine); CMyWin cmyWin; cmyWin.MyRegisterClass(hInstance);
if (!cmyWin.InitInstance(hInstance,nCmdShow))
{
return 0;
} return cmyWin.RunMessage();
}为什么不能捕获WM_CREATE消息,窗口类型不是对话框啊,还有就是这样封装有什么问题吗?想自己封装API可是不知道该怎么封装,一头雾水,大家平时都怎么封装啊,提点意见,或提供点资料吧,谢谢

解决方案 »

  1.   

    你在CreateWindow之后才调用SetWindowLongPtr(m_hWnd, GWL_USERDATA, (LONG)(LONG_PTR)this); 而此时WM_CREATE消息已经处理完毕(在CreateWindow中已经处理)。参考MFC类,看看《深入浅出MFC》。简单来说,假定程序只拥有一个主窗口(一般就是这样),那么用一个静态变量或者全局变量保存这个唯一的窗口实例指针,用于回调消息函数中的访问;或者用另外一个类,就是MFC中的CWinApp类来保存。MFC中的CWinApp类成员变量m_pMainWnd就是这个作用。
      

  2.   

    看下MFC的代码,封装窗口类就是省去句柄操作,MFC做得很好了
      

  3.   

    那我们平时直接用API来写程序,不用MFC框架,如果自己想把他封装起来的话,大家一般也用的是MFC的思想和方法来封装API吗
      

  4.   

    基本是模仿,MFC不单是类封装,他还提供一个编程框架,不用MFC的话我们平时就是简单封装下类而已
      

  5.   

    SetWindowLongPtr(m_hWnd, GWL_USERDATA, (LONG)(LONG_PTR)this); 
    其实CreateWindow的时候就可以把this作为最后一个参数,这样在WM_CREATE消息里面就能在
    ((LPCREATESTRUCT)lParam)->lpCreateParams得到,然后你再SetWindowLongPtr就可以了。你这种封装方式有个致命弱点:如果调用者出于一些目的也调用了SetWindowLongPtr(m_hWnd, GWL_USERDATA, ...)设置自己的数据,就会把你这个this指针冲掉,程序崩溃。可以看看下面这篇文章:
    打造自己的MFC:thunk技术实现窗口类的封装