Windows编程之最简单窗口程序

一、一些基本知识介绍
Data type Size Signed?
BYTE 8 bits Unsigned
DWORD 32 bits Unsigned
INT32 32 bits Signed
INT64 64 bits Signed
LONG 32 bits Signed
LONGLONG 64 bits Signed
UINT32 32 bits Unsigned
UINT64 64 bits Unsigned
ULONG 32 bits Unsigned
ULONGLONG 64 bits Unsigned
WORD 16 bits Unsigned
WinDef.h中定义了BOOL值
#define FALSE    0 
#define TRUE     1

p代表“指针”
lp代表“长指针

  • DWORD_PTR
  • INT_PTR
  • LONG_PTR
  • ULONG_PTR
  • UINT_PTR

头文件WinNT.h定义了如下typedef (基于UTF-16编码,即是16bit),为了支持Unicode

typedef wchar_t WCHAR;
一般来说,会经常看到如下编码的宽字符,即是前面加个L:
wchar_t a = L'a';
wchar_t *str = L"hello";
其他一些相关的typedef
Typedef Definition
CHAR char
PSTR or LPSTR char*
PCSTR or LPCSTR const char*
PWSTR or LPWSTR wchar_t*
PCWSTR or LPCWSTR const wchar_t*
windows支持unicode与ANSI,较新的则只支持Unicode
  • SetWindowTextA takes an ANSI string.
  • SetWindowTextW takes a Unicode string.
#ifdef UNICODE
#define SetWindowText  SetWindowTextW
#else
#define SetWindowText  SetWindowTextA
#endif 
通过宏UNICODE来控制
Macro Unicode ANSI
TCHAR wchar_t char
TEXT("x") L"x" "x"
示范例子:


SetWindowTextW(L"My Application"); // Unicode function with wide-character string.

SetWindowTextA("My Application");  // ANSI function.
#ifdef _UNICODE
#define _tcslen     wcslen
#else
#define _tcslen     strlen
#endif 

二、windows窗口编程
1、窗口句柄
HWND,通常来自以下两个函数的返回值
要操作窗口通常需要使用HWND作为参数传入函数使用,例如移动窗口MoveWindow
BOOL MoveWindow(HWND hWnd, int X, int Y, int nWidth, int nHeight, BOOL bRepaint);
另外句柄不是指针,不存在 *hwnd  
2、屏幕和窗口坐标
一般来说,windows的窗口都是以左上角为原点(0,0),另外一些坐标定义如图(图片来自msdn)

3、windows编程的入口点
WinMain or wWinMain
wWinMain为例子
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow);
hInstance:标识executable
hPrevInstance:现在已经没有使用,始终为0,以前用在16位的windows中。
pCmdLine:包含Unicode字符串的命令行参数
nCmdShow:一个flag,表示应用程序窗口的显示如:最大化,最小化或者正常。

4、创建一个窗口的过程
(1)注册一个窗口类
    // Register the window class.
    const wchar_t CLASS_NAME[]  = L"Sample Window Class";
    
    WNDCLASS wc = { };

    wc.lpfnWndProc   = WindowProc;
    wc.hInstance     = hInstance;
    wc.lpszClassName = CLASS_NAME;
lpfnWndProc:窗口过程,定义了绝多部分的动作
hInstance:来自wWinMain,实例句柄
lpszClassName:标识窗口类的字符串

传递WNDCLASS结构的地址给RegisterClass函数,注册窗口类到操作系统。
  RegisterClass(&wc);
(2)创建窗口新实例
 HWND hwnd = CreateWindowEx(
        0,                              // Optional window styles.
        CLASS_NAME,                     // Window class

        L"Learn to Program Windows",    // Window text
        WS_OVERLAPPEDWINDOW,            // Window style

        // Size and position
        CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,

        NULL,       // Parent window    
        NULL,       // Menu
        hInstance,  // Instance handle
        NULL        // Additional application data
        );

    if (hwnd == NULL)
    {
        return 0;
    }
第一个参数:
Optional window styles.
设定窗口中的一些可选行为(例如透明窗口),默认为0。
第二个参数:
Window class
定义窗口所创建的类型
第三个参数:
Window text
窗口标题,如果窗口存在标题栏则显示在其中。
第四个参数:
Window style

窗口的风格,定义了一些窗口外观和表现的标志组合,WS_OVERLAPPEDWINDO是几个标志结合的位或,包含最小化,最大化按钮,边框,标题栏等等

第五个参数:

Size and position

位置和大小 CW_USEDEFAULT 使用默认值

第六个参数:

Parent window 

父窗口。

第七个参数:

Menu

菜单

第八个参数:

Instance handle

实例句柄

第九个参数:

Additional application data

指向void*的任意数据结构,传递数据所用

最后CreateWindowEx 返回句柄创建新窗口,如果失败返回0.

(3)显示窗口

要显示窗口则将窗口句柄传递给ShowWindow函数

ShowWindow(hwnd, nCmdShow);

  hwnd  参数来自 CreateWindowEx 

nCmdShow参数用于最大化或者最小化窗口。操作系统将通过wWinMain函数传递该参数给程序


(4)窗口消息

窗口消息

MSG msg;GetMessage(&msg, NULL, 0, 0);

提取消息使用以下两个函数

TranslateMessage(&msg); DispatchMessage(&msg);


退出提取消息循环

退出提取消息循环

        PostQuitMessage(0);
  WM_QUIT是一个特殊的消息,它会令消息循环结束。消息循环的示例:
// Correct.

MSG msg = { };
while (GetMessage(&msg, NULL, 0, 0))
{
    TranslateMessage(&msg);
    DispatchMessage(&msg);
}

(4)窗口过程

The 
DispatchMessage function calls the window procedure of the window that is the target of the message. The window procedure has the following signature.

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
hwnd:窗口句柄
uMSg:消息代码
wParam、lParam:消息的其他数据

典型的窗口过程如下:

switch (uMsg)
{
case WM_SIZE: // Handle window resizing
    
// etc

}

一个典型的窗口过程可能需要处理几十条消息,因此它可能会变得非常长,这样可以将每个消息的逻辑处理封装到一个单独的函数中n,
然后再在switch中处理。
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch (uMsg)
    {
    case WM_SIZE: 
        {
            int width = LOWORD(lParam);  // Macro to get the low-order word.
            int height = HIWORD(lParam); // Macro to get the high-order word.

            // Respond to the message:
            OnSize(hwnd, (UINT)wParam, width, height);
        }
        break;
        
    }
}

void OnSize(HWND hwnd, UINT flag, int width, int height);
{
    // Handle resizing
}
假如不处理窗口过程特定的消息,可以直接返回默认的DefWindowProc函数,
    return DefWindowProc(hwnd, uMsg, wParam, lParam);hui


(4)绘制窗口内容

  switch (uMsg)
    {

    case WM_PAINT:
        {
            PAINTSTRUCT ps;
            HDC hdc = BeginPaint(hwnd, &ps);

            // All painting occurs here, between BeginPaint and EndPaint.

            FillRect(hdc, &ps.rcPaint, (HBRUSH) (COLOR_WINDOW+1));

            EndPaint(hwnd, &ps);
        }
        return 0;

    }
更新绘图有两种选择:
*只更新一部分
*更新全部区域

下面代码是更新整个区域,使用单一颜色,采用系统默认的COLOR_WINDOW,颜色取决于系统的配色方案
 FillRect(hdc, &ps.rcPaint, (HBRUSH) (COLOR_WINDOW+1));

完成绘图后,需要调用EndPaint,清除更新区域,表示绘图已经完成

三、最后的完整代码
[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. #ifndef UNICODE  
  2. #define UNICODE  
  3. #endif  
  4.   
  5. #include <Windows.h>  
  6.   
  7. LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);  
  8.   
  9. int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCEPWSTR pCmdLine, int nCmdShow)  
  10. {  
  11.     //Register the window class  
  12.     const wchar_t CLASS_NAME[] = L"Sample Window Class";  
  13.     WNDCLASS wc = { };  
  14.     wc.lpfnWndProc  = WindowProc;  
  15.     wc.hInstance    = hInstance;  
  16.     wc.lpszClassName    =   CLASS_NAME;  
  17.   
  18.     RegisterClass(&wc);  
  19.   
  20.     //Create the window.  
  21.   
  22.     HWND hwnd = CreateWindowEx(  
  23.         0,              //Optional window styles.  
  24.         CLASS_NAME,     //Window class  
  25.         L"Learn to Program Windows",    //Window text  
  26.         WS_OVERLAPPEDWINDOW,    //Window style  
  27.   
  28.         //Size and position  
  29.         CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,  
  30.   
  31.         NULL,               //Parent window  
  32.         NULL,               //Menu  
  33.         hInstance,          //Instance handle  
  34.         NULL                //Additional application data  
  35.         );  
  36.   
  37.     if(hwnd == NULL)  
  38.     {  
  39.         return 0;  
  40.     }  
  41.   
  42.     ShowWindow(hwnd, nCmdShow);  
  43.   
  44.     //Run the message loop.  
  45.   
  46.     MSG msg = { };  
  47.     while (GetMessage(&msg, NULL, 0, 0))  
  48.     {  
  49.         TranslateMessage(&msg);  
  50.         DispatchMessage(&msg);  
  51.     }  
  52.     return 0;  
  53. }  
  54.   
  55. LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)  
  56. {  
  57.     switch (uMsg)  
  58.     {  
  59.     case WM_DESTROY:  
  60.             PostQuitMessage(0);  
  61.             return 0;  
  62.         case WM_PAINT:  
  63.             {  
  64.                 PAINTSTRUCT ps;  
  65.                 HDC hdc = BeginPaint(hwnd, &ps);  
  66.                 FillRect(hdc, &ps.rcPaint, (HBRUSH)(COLOR_WINDOW+1));  
  67.                 EndPaint(hwnd, &ps);  
  68.             }  
  69.             return 0;  
  70.     }  
  71.     return DefWindowProc(hwnd, uMsg, wParam, lParam);  
  72. }  
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值