创建一个window窗口:
创建一个窗体,必须先注册,再创建,后显示。需要用到:
RegisterClassEx、CreateWindowEx、ShowWindow、UpdateWindow定义在windows.h
1.注册一个window类:
- ATOM RegisterClassEx(CONST WNDCLASSEX *Ipwcx);
参数:
WNDCLASSEX:一个结构体,描述了窗口的一些行为特征,例如鼠标,光标的长相之类的,还指定了谁处理它的事件(一个回调函数)
- WNDCLASSEX wc;
- wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
- wc.lpfnWndProc = WndProc; //指定回调函数
- wc.cbClsExtra = 0;
- wc.cbWndExtra = 0;
- wc.hInstance = m_hinstance;
- wc.hIcon = LoadIcon(NULL, IDI_WINLOGO);
- wc.hIconSm = wc.hIcon;
- wc.hCursor = LoadCursor(NULL, IDC_ARROW);
- wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); //默认黑色窗口黑色背景
- wc.lpszMenuName = NULL;
- wc.lpszClassName = m_applicationName;
- wc.cbSize = sizeof(WNDCLASSEX);
参数:
wc.hInstance:应用程序实例句柄,一个应用程序是可以有多个窗体的,这里指定此窗体是属于那个应用实例的。应用实例的获取:GetModuleHandle(NULL); 参数为null就是获取当前应用。
wc.lpfnWndProc:指定一个回调函数,这个回调函数用于处理事件。
wc.style:窗口的显示样式。有以下这些类型:
- #define CS_VREDRAW 0x0001 // 垂直变化时,重绘
- #define CS_HREDRAW 0x0002 // 水平变化时,重绘
- #define CS_KEYCVTWINDOW 0x0004
- #define CS_DBLCLKS 0x0008 // 不忽略鼠标双击的消息
- #define CS_OWNDC 0x0020 // 给用该类建立的每一个窗口分配独立的设备 DC
- #define CS_CLASSDC 0x0040 // 让属于该类的所有窗口共享一个设备 DC
- #define CS_PARENTDC 0x0080 // 允许窗口的子窗口继承一些共同特性
- #define CS_NOKEYCVT 0x0100
- #define CS_NOCLOSE 0x0200 // 禁用系统菜单的 Close命令,同时窗口没有关闭按钮
- #define CS_SAVEBITS 0x0800 // 当窗口被覆盖时, 用位图缓存被覆盖区, 从而避免 WM_PAINT 消息, 一般用于菜单或对话框
- #define CS_BYTEALIGNCLIENT 0x1000
- #define CS_BYTEALIGNWINDOW 0x2000
- #define CS_GLOBALCLASS 0x4000 // 全局窗口类, 一般用于 DLL; 没有此选项, 窗口类和窗口建立函数中指定的实例句柄须相同
- #define CS_IME 0x00010000
DC:又称设备场景,GUI里面的一个概念,相当于真正绘制工具的一个描述它的结构,里面有背景颜色之类的属性。
2.创建和显示window窗体:
- HWND CreateWindowEx(
- DWORD dwExStyle, // 扩展窗口样式,后文介绍
- LPCTSTR lpClassName, // 窗口类名,同RegisterClassEx中设置
- LPCTSTR lpWindowName, // 窗口标题
- DWORD dwStyle, // 窗口样式,后文介绍
- int x, // 窗口左上角的X坐标
- int y, // 窗口左上角的Y坐标
- int nWidth, // 窗口宽度
- int nHeight, // 窗口高度
- HWND hWndParent, // 父窗体句柄,若窗体为主窗体,则设为NULL
- HMENU hMenu, // 菜单句柄,不需要则设为NULL
- HINSTANCE hInstance, // 程序句柄,同RegisterClassEx中设置
- LPVOID lpParam // 创建多文档界面时用到,现设为NULL
- );
dwExStyle:比较常用的样式,dwExStyle的样式都有_EX
- WS_EX_ACCEPTFILES //接受文件拖放
- WS_EX_APPWINDOW //使可见的顶级窗口出现在任务栏上
- WS_EX_CLIENTEDGE //使用凹陷边框
- WS_EX_DLGMODALFRAME //使用双线边框
- WS_EX_CONTEXTHELP //标题栏上加入问号按钮
- WS_EX_WINDOWEDGE //使用突出边框
dwStyle:比较常用的样式
- WS_BORDER //使用细线边框
- WS_CAPTION //标题栏
- WS_HSCROLL //水平滚动条
- WS_MAXIMIZE //初始状态为最大化
- WS_VSCROLL //垂直滚动条
实例:
- HWND m_hwnd = CreateWindowEx(WS_EX_APPWINDOW, m_applicationName, m_applicationName,
- WS_OVERLAPPEDWINDOW,
- posX, posY, screenWidth, screenHeight, NULL, NULL, m_hinstance, NULL);
- // 显示窗口并设置其为焦点.
- ShowWindow(m_hwnd, SW_SHOW);
- SetForegroundWindow(m_hwnd); // 显示到最前面
- SetFocus(m_hwnd);
- UpdateWindow(m_hwnd);
3.创建全屏窗体:其基本思路是零时对显示设备的属性进行修改,并且制定显示模式。
- LONG ChangeDisplaySettings (LPDEVMODE lpDevMode, DWORD dwflags);
lpDevMode:是一个EVMODE类型的结构体的指针。
dwflags:表明了图形模式如何改变。关于这个两个参数的具体细节可参考:
http://baike.baidu.com/view/1080516.htm
- //全屏模式下,设置窗口大小为windows桌面分辨率.
- DEVMODE dmScreenSettings;
- memset(&dmScreenSettings, 0, sizeof(dmScreenSettings)); //清空内存,填充值为0
- dmScreenSettings.dmSize = sizeof(dmScreenSettings);
- dmScreenSettings.dmPelsWidth = (unsigned long)screenWidth;
- dmScreenSettings.dmPelsHeight = (unsigned long)screenHeight;
- dmScreenSettings.dmBitsPerPel = 32;
- dmScreenSettings.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
- // 临时设置显示设备为全屏模式,注意:应用程序退出时候,将恢复系统默认设置。
- ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN);
注意:临时设置显示设备是在创建窗体之前。在调用CreateWindowEx方法前面加上这些就行了。
4.消息循环:
消息结构:
- typedef struct tagMSG {
- HWND hwnd; //窗体句柄
- UINT message; //消息的标识符
- WPARAM wParam; // 具体内存,例如按的是什么键之类
- LPARAM lParam; // 具体内存,例如按的是什么键之类
- DWORD time; // 时间
- POINT pt; // 鼠标的位置
- } MSG;
消息循环:
- MSG msg;
- bool done=false, result = 1;
- //1.初始化消息结构.
- ZeroMemory(&msg, sizeof(MSG));
- //2.循环进行消息处理
- while(!done)
- {
- //1.处理windows消息.
- if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
- {
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }
- //2.接收到WM_QUIT消息,退出程序.
- if(msg.message == WM_QUIT)
- {
- done = true;
- }
- }
PeekMessage:获取消息,还有一种方式,可以到网上查找。
TranslateMessage:组合消息,例如把按下和弹起合并为一个消息
DispatchMessage:处理消息,这个时候会调上面提到的那个回调函数。
消息处理回调函数:
- LRESULT CALLBACK WndProc(HWND hwnd, UINT umessage, WPARAM wparam, LPARAM lparam)
- {
- switch(umessage)
- {
- // 窗口销毁消息.
- case WM_DESTROY:
- {
- PostQuitMessage(0);
- return 0;
- }
- //MessageHandle过程处理其它所有消息.
- default:
- {
- //任何其它消息发送到windows缺省处理.
- return DefWindowProc(hwnd, umsg, wparam, lparam);
- }
- }
- }
这里需要注意的第一个就是函数的参数,就是上面MSG结构里面的几个值。另外就是PostQuitMessage的作用相当于发出一个WM_QUIT消息,参数0是消息码。DefWindowProc是window默认处理消息的函数,所有程序不想处理的消息都给它处理。
5.销毁应用实例:
- UnregisterClass(m_applicationName, m_hinstance);