C++下Windows 程序编程
Windows API的Windows程序,需要编写两个函数。一个是Winmain()函数,程序的执行从这里开始,基本的初始化工作也在这里完成。另一个是WindowProc()函数,该函数由Windows调用,用来给应用程序传递消息。Winmain与WindowProc函数通过调用系统的API与Windows通信,如图所示:
1 Winmain函数
Winmain()函数等价于控制台的程序中的main()函数,Winmain()函数的原型如下:
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow);
(1) WINAPI是一个Windows定义的宏,将使系统以特定于Windows API函数的特种方式处理函数名和实参。
(2) hInstance是指向某个实例的的句柄。
(3) hPrevInstance是16位操作系统继承下来的,现在的操作系统可以将这位始终设为空。
(4) lpCmdLine是指向某个字符串的指针,该字符串包括启动程序的命令行字符。
(5) nCmdShow决定着被创建窗口的外观。
程序中的Winmain()函数需要做以下四件事情:
(1) 指定程序窗口种类
(2) 创建窗口
(3) 初始化窗口
(4) 处理部分消息
1.1 指定程序窗口
Windows使用WNDCLASSEX来包含用来指定窗口的数据,WNDCLASSEX 结构用于注册窗口类,WNDCLASSEX的结构定义如下:
struct WNDCLASSEX {
UINT cbSize; // WNDCLASSEX 的大小
UINT style; //窗口类的样式,它的值可以是窗口样式值的任意组合
WNDPROC lpfnWndProc; //指向窗口处理消息的函数的指针
int cbClsExtra; //允许请求Windows在内部为特别用途提供额外空间,常用初始化为0
int cbWndExtra; //允许请求Windows在内部为特别用途提供额外空间,常用初始化为0
HINSTANCE hInstance; //当前应用程序的实例句柄
HICON hIcon; //最小化时的应用程序
HCURSOR hCursor; //窗口使用的光标
HBRUSH hbrBackground; //窗口客户区的背景色
LPCTSTR lpszMenuName; //定义窗口菜单的资源名称;如果窗口没有菜单,则定义为NULL
LPCTSTR lpszClassName; //指向窗口类的指针,LPSTR类型
HICON hIconSm; //小图标的句柄,在任务栏显示的图标
};
1.2 创建程序窗口
将WNDCLASSEX结构的所有成员都设置为所需的值后,下一步是把相关情况告诉Windows。使用RegisterClassEx()来完成这件事。假定WNDCLASSEX的对象是WindowsClass,则相应的语句如下所示:
RegisterClassEx(&WindowsClass);//注册窗口类
接下来是创建窗口,由createWindow()函数完成。
HWND hWnd; //窗体句柄
hWnd = CreateWindow(
szAppName, // the window class name
_T("A Basic Window the Hard Way"), //标题栏文本
WS_OVERLAPPEDWINDOW, // 创建后的窗体样式
CW_USEDEFAULT, // 窗体位置
CW_USEDEFAULT, // 左上角位置坐标
CW_USEDEFAULT, // 窗体长度
CW_USEDEFAULT, // 窗体高度
nullptr, // 如果不是父窗体设置为空
nullptr, // 没有菜单设置为空
hInstance, // Program Instance handle
nullptr // No window creation data
);
在调用CreateWindow()函数后,被创建的窗口现在已经存在,但是还没有显示在屏幕上。需要调用另一个Windows API函数将该窗口显示出来:
ShowWindow(hWnd, nCmdShow);
第一个参数是CreateWindow()函数返回的句柄。第二个参数是给Winmain()传递的nCmdShow值,它指出在屏幕显示窗口的方式。
1.3 初始化程序窗口
在调用 ShowWindow()函数后,该窗口将出现在屏幕上,但仍然没有应用程序的内容。绘制工作区的最好方法是把绘制工作区的代码放入WindowProc()函数,并使Windows给程序发送请求重画工作区的消息。调用另一个Windows API函数UpdateWindow(),请求Windows给程序发送一条重画窗口工作区的消息。调用该函数的窗口如下:
UpdateWindow(hwnd);
1.4 处理Windows消息
Windows有两种消息:一种是排队消息,Winmain()从队列中提取这些消息进行处理,称为消息循环;另一种是致使Windows直接调用WindowsProc()函数的非排队消息。我们在Winmain()函数的消息循环中所作的事情是从Windows为应用程序排好的消息队列中提取一条消息,然后请求Windows调用WindowsProc()函数来处理该消息。
while (GetMessage(&msg, nullptr, 0, 0) == TRUE) // Get any messages
{
TranslateMessage(&msg); // Translate the message
DispatchMessage(&msg); // Dispatch the message
}
- GetMessage()——从队列中检索一条消息
- TranslateMessage()——对检索的消息执行必要的转换
- DispatchMessage()——使Windows调用应用程序的WindowProc()函数来处理消息
2 处理Windows消息
使Windows以我们希望的方式运行的所有代码都在程序的消息处理部分——WindowProc()函数
2.1 WindowProc()函数
WindowProc()函数的原型如下:
LRESULT CALLBACK WindowProc(HWND hWnd, UINT message,WPARAM wParam, LPARAM lParam);
可以使用WINAPI替代CALLBACK,但后者更好地表达出这个函数的作用。每个参数的意义如下:
HWND hWnd : 一个句柄,事件引起消息发生的窗口
UINT message: 消息的ID,指出消息类型的32为整数值
WPARAM wParam : 32位值,包含附加信息,决定于消息的种类
LPARAM lParam: 32位值
2.2 解码Windows消息
switch (message) // Process selected messages
{
case WM_PAINT:
//绘制窗口工作区的代码
break;
case WM_LBUTTONDOWN:
//处理鼠标左键按下时的事件
break;
case WM_LBUTTONUP:
//处理鼠标释放时的事件
break;
......
case WM_DESTROY: // Window is being destroyed
//退出窗口
break;
default:
//其他默认语句
}
3 完整程序代码
[code]// Ex11_01.cpp Native windows program to display text in a window #include <windows.h> #include <tchar.h> LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); // Listing OFWIN_1 int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { WNDCLASSEX WindowClass; // Structure to hold our window's attributes static LPCTSTR szAppName { _T("OFWin") }; // Define window class name HWND hWnd; // Window handle MSG msg; // Windows message structure WindowClass.cbSize = sizeof(WNDCLASSEX); // Set structure size // Redraw the window if the size changes WindowClass.style = CS_HREDRAW | CS_VREDRAW; // Define the message handling function WindowClass.lpfnWndProc = WindowProc; WindowClass.cbClsExtra = 0; // No extra bytes after the window class WindowClass.cbWndExtra = 0; // structure or the window instance WindowClass.hInstance = hInstance; // Application instance handle // Set default application icon WindowClass.hIcon = LoadIcon(nullptr, IDI_APPLICATION); // Set window cursor to be the standard arrow WindowClass.hCursor = LoadCursor(nullptr, IDC_ARROW); // Set gray brush for background color WindowClass.hbrBackground = static_cast<HBRUSH>(GetStockObject(GRAY_BRUSH)); WindowClass.lpszMenuName = nullptr; // No menu WindowClass.lpszClassName = szAppName; // Set class name WindowClass.hIconSm = nullptr; // Default small icon // Now register our window class RegisterClassEx(&WindowClass); // Now we can create the window hWnd = CreateWindow( szAppName, // the window class name _T("A Basic Window the Hard Way"), // The window title WS_OVERLAPPEDWINDOW, // Window style as overlapped CW_USEDEFAULT, // Default screen position of upper left CW_USEDEFAULT, // corner of our window as x,y. CW_USEDEFAULT, // Default window size width ... CW_USEDEFAULT, // ... and height nullptr, // No parent window nullptr, // No menu hInstance, // Program Instance handle nullptr // No window creation data ); ShowWindow(hWnd, nCmdShow); // Display the window UpdateWindow(hWnd); // Redraw window client area // The message loop while (GetMessage(&msg, nullptr, 0, 0) == TRUE) // Get any messages { TranslateMessage(&msg); // Translate the message DispatchMessage(&msg); // Dispatch the message } return static_cast<int>(msg.wParam); // End, so return to Windows } // Listing OFWIN_2 LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) // Process selected messages { case WM_PAINT: // Message is to redraw the window HDC hDC; PAINTSTRUCT PaintSt; // Structure defining area to be drawn hDC = BeginPaint(hWnd, &PaintSt) ; // Prepare to draw the window // Get upper left and lower right of client area RECT aRect; // A working rectangle GetClientRect(hWnd, &aRect); SetBkMode(hDC, TRANSPARENT); // Set text background mode // Now draw the text in the window client area DrawText( hDC, // Device context handle _T("But, soft! What light through yonder window breaks?"), -1, // Indicate null terminated string &aRect, // Rectangle in which text is to be drawn DT_SINGLELINE | // Text format - single line DT_CENTER | // - centered in the line DT_VCENTER); // - line centered in aRect EndPaint(hWnd, &PaintSt); // Terminate window redraw operation return 0; case WM_DESTROY: // Window is being destroyed PostQuitMessage(0); return 0; } return DefWindowProc(hWnd, message, wParam, lParam); }
- Windows编程 - 启动可执行(exe)程序 代码(C++)
- C/C++_log2000_windows编程之第一个控制台程序项目part2
- C/C++ socket编程教程之三:Windows下的socket程序
- Windows编程 - 终止可执行(exe)程序 代码(C++)
- Windows编程C++之第一个Windows程序
- Windows编程 - 遍历程序使用的动态链接库(dll) 代码(C++)
- C/C++ socket编程教程之三:Windows下的socket程序
- Windows编程 - 开启/关闭/遍历程序的类 代码(C++)
- 用C/C++创建windows服务程序
- Windows 7下使用GNU工具编译C/C++程序的环境搭建
- 初步学习:Eclipse3.6开发C/C++程序(Windows下)
- Windows下通过命令行编译C/C++程序
- Windows下使用Sublime Text 3调试/运行 C/C++ 程序
- c++写windows服务程序
- TCP Socket编程 C/C++实现 (Windows Platform SDK)
- 用C语言编写 Windows 服务程序的五个步骤以及服务编程常见问题处理
- 关于c++检测内存泄露相关知识(windows程序调试)
- Windows下通过Dev-C++配置GTK+3.0编程环境
- C++ STM32 编程 007 正式编写第一个程序
- C++ 学习之旅 Windows程序内部运行原理