项目的创建和配置:
1、新建一个 Win32 空项目
2、创建源码文件夹、库文件夹和资源文件夹
3、在 VS2013(我使用的 IDE 是 vs2013)配置这些文件夹
这里使用了 $(SolutionDir) 宏来指定上面创建的文件夹,因为使用的不是绝对路径,所以将项目拷贝到其他文件夹或电脑也可以正确读取。通过上面的设置,告诉程序去哪找到源码文件和库文件。
创建窗口:
创建窗口有几个固定的步骤,只要按照这些步骤来就好了,下面是创建的代码
HWND Create() { /* 设计窗口类 */ WNDCLASS wndclass; memset(&wndclass, 0, sizeof(WNDCLASSA)); wndclass.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS; wndclass.lpfnWndProc = ( WNDPROC ) WindowProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = ( HINSTANCE ) GetModuleHandle(0); wndclass.hIcon = 0; wndclass.hCursor = 0; wndclass.hbrBackground = CreateSolidBrush(RGB(255, 255, 255)); wndclass.lpszMenuName = 0; wndclass.lpszClassName = L"MMDViewer"; /* 注册窗口类 */ RegisterClass(&wndclass); /* 不能改变窗口大小 */ int style = WS_OVERLAPPEDWINDOW & ~WS_THICKFRAME & ~WS_MAXIMIZEBOX; /* 根据客户区大小计算窗口大小 */ RECT rect = { 0, 0, 800, 600 }; AdjustWindowRect(&rect, style, 0); /* 居中显示计算窗口位置和大小 */ int w = rect.right - rect.left; int h = rect.bottom - rect.top; int x = (GetSystemMetrics(SM_CXSCREEN) - w) / 2; int y = (GetSystemMetrics(SM_CYSCREEN) - h) / 2; /* 创建窗口 */ HWND hwnd = CreateWindow(L"MMDViewer", L"MMDViewer", style, x, y, w, h, NULL, 0, ( HINSTANCE ) GetModuleHandle(0), 0); /* 显示窗口 */ ShowWindow(hwnd, SW_SHOWNORMAL); UpdateWindow(hwnd); return hwnd; }
该函数返回新建的窗口句柄,需要注意的是,这里重新计算了窗口的大小。如果按 800x600 创建窗口,则窗口客户区的大小就会小于 800x600,因为客户区才是真正渲染的区域,所以希望客户区的大小就是 800x600,而窗口的大小需要重新计算。使用的函数是 AdjustWindowRect(),它能过返回窗口的需要大小。
还有就是窗口事件处理函数,这里添加了可以使窗口关闭的代码:
LRESULT CALLBACK WindowProc(HWND wnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch ( msg ) { case WM_CLOSE: case WM_DESTROY: PostQuitMessage(0); break; case WM_PAINT: RECT rect; if ( GetUpdateRect(wnd, &rect, FALSE) ) { ValidateRect(wnd, &rect); } break; } return DefWindowProc(wnd, msg, wParam, lParam); }
最后就是事件循环,它在主函数中:
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow) { UNREFERENCED_PARAMETER(hPrevInstance); UNREFERENCED_PARAMETER(lpCmdLine); HWND hwnd = Create(); /* 主事件循环 */ MSG msg = { 0 }; while ( WM_QUIT != msg.message ) { if ( PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) ) { TranslateMessage(&msg); DispatchMessage(&msg); } } return ( int ) msg.wParam; }
编译程序,成功运行后就会弹出一个窗口:
源码下载:MMDViewer 02.zip