windows学习记录----hello world与窗口创建

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了windows学习记录----hello world与窗口创建相关的知识,希望对你有一定的参考价值。

 

1.第一个程序:Hello,world!

1 #include<windows.h>
2 
3 int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow )
4 {
5     MessageBox( NULL, TEXT("Hello,world!"), TEXT("MessageBox"), 0 );
6
7    return 0;
8 }

技术分享

WinMain()函数
WINAPI为WinMain函数的调用规则, 在WINDEF.H对"WINAPI"作出了如下宏定义:
#define WINAPI __stdcall
WinMain函数的调用规则为"__stdcall"方式, 对于"__stdcall"调用规则, 具体用法待查
 
 
WinMain函数的参数:
1.HINSTANCE hInstance:实例句柄
2.HINSTANCE hPrevInstance:前一个的实例句柄,历史原因,已无实际意义,总为NULL。
3.LPSTR lpCmdLine:PSTR:运行程序的命令行。PSTR来指向一个字符串的指针类型, szCmdLine, sz:表示以0结尾的字符串;
目的是通过命令行方式运行程序并向主函数中传入参数, 应该就像给main函数传入参数一样。暂未遇到具体命令程序,待学习。 4.程序(窗口)最初如何被显示, 例如最小化?最大化?全屏?暂未遇到具体命令程序,待学习。
MessageBox函数:

int MessageBox(
  HWND hWnd,          // handle of owner window, 窗口的一个句柄
  LPCTSTR lpText,     // address of text in message box, 一个文本(字符串)的指针
  LPCTSTR lpCaption,  // address of title of message box, 标题字符串的指针
  UINT uType          // style of message box, 对话框的风格
);

MessageBox( NULL, TEXT("Hello,world!"), TEXT("MessageBox"), 0 );
第一个参数窗口的句柄的实参为NULL, 意思为不属于任何窗口.
第二个参数为对话框的内容, 
第三个参数为对话框的标题, 但是这两个参数都使用了一个TEXT()的函数,
      当使用wchar_t类型的宽字符时, 使用"令牌粘贴",  使用TEXT宏时就避免了在字符串前面加上一个大写字母‘L‘了。
                  
#define __T(x)      L ## x

#define _TEXT(x)    __T(x)

#define __TEXT(quote)  L##quote  

#define TEXT(quote)  __TEXT(quote)
第四个参数为对话框的风格, 一些以MB_开头的一些常量的组合, 可以使用OR(|)运算进行组合, 这些常量定义在WINUSER.H中, 例如常用的有:
1>.对话框按钮类型:

    #define MB_OK                       0x00000000L            //仅有一个"确定"按钮
    #define MB_OKCANCEL                 0x00000001L            //"确定" + "取消"
    #define MB_ABORTRETRYIGNORE         0x00000002L            //"终止" + "重试" + "忽略"
    #define MB_YESNOCANCEL              0x00000003L            //"是" + "否" + "取消"
    #define MB_YESNO                    0x00000004L            //"是" + "否"
    #define MB_RETRYCANCEL              0x00000005L            //"重试" + "取消"

 
2>.对话框中的图标类型:  
#define MB_ICONHAND                 0x00000010L            //一个红X的错误/停止图标
#define MB_ICONQUESTION 0x00000020L //一个问号的询问图标
#define MB_ICONEXCLAMATION 0x00000030L //一个黄色感叹号的警告图标
#define MB_ICONASTERISK 0x00000040L //一个带有i的信息提示图标 同时, 在这些图标中有的还可以用其他名称代替, 这些别名在WINUSER.H的定义如下: #define MB_ICONWARNING MB_ICONEXCLAMATION //警告
#define MB_ICONERROR MB_ICONHAND //错误
#define MB_ICONINFORMATION MB_ICONASTERISK //信息
#define MB_ICONSTOP MB_ICONHAND //停止

  2.创建自己的窗口

 

 1 #include <windows.h>
 2 
 3 LRESULT CALLBACK WndProc( HWND, UINT, WPARAM, LPARAM ) ;        //声明用来处理消息的函
 4 
 5 int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow )
 6 {
 7     static TCHAR szAppName[] = TEXT("MyWindow") ;
 8     HWND hwnd ;
 9     MSG msg ;
10     WNDCLASS wndclass ;        //声明一个窗口类对象
11 
12     //以下为窗口类对象wndclass的属性
13     wndclass.style = CS_HREDRAW | CS_VREDRAW ;                         //窗口样式
14     wndclass.lpszClassName = szAppName ;                               //窗口类名
15     wndclass.lpszMenuName = NULL ;                                     //窗口菜单:无
16     wndclass.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH) ;    //窗口背景颜色
17     wndclass.lpfnWndProc = WndProc ;                                   //窗口处理函数
18     wndclass.cbWndExtra = 0 ;                                          //窗口实例扩展:无
19     wndclass.cbClsExtra = 0 ;                                          //窗口类扩展:无
20     wndclass.hInstance = hInstance ;                                   //窗口实例句柄
21     wndclass.hIcon = LoadIcon( NULL, IDI_APPLICATION ) ;               //窗口最小化图标:使用缺省图标
22     wndclass.hCursor = LoadCursor( NULL, IDC_ARROW ) ;                 //窗口采用箭头光标
23 
24     if( !RegisterClass( &wndclass ) )
25     {    //注册窗口类, 如果注册失败弹出错误提示
26         MessageBox( NULL, TEXT("窗口注册失败!"), TEXT("错误"), MB_OK | MB_ICONERROR ) ;
27         return 0 ;
28     }
29 
30     hwnd = CreateWindow(                   //创建窗口
31                 szAppName,                 //窗口类名
32                 TEXT("我的窗口"),           //窗口标题
33                 WS_OVERLAPPEDWINDOW,       //窗口的风格
34                 CW_USEDEFAULT,             //窗口初始显示位置x:使用缺省值
35                 CW_USEDEFAULT,             //窗口初始显示位置y:使用缺省值
36                 CW_USEDEFAULT,             //窗口的宽度:使用缺省值
37                 CW_USEDEFAULT,             //窗口的高度:使用缺省值
38                 NULL,                      //父窗口:无
39                 NULL,                      //子菜单:无
40                 hInstance,                 //该窗口应用程序的实例句柄 
41                 NULL                       //
42             ) ;
43 
44     ShowWindow( hwnd, iCmdShow ) ;        //显示窗口
45     UpdateWindow( hwnd ) ;                //更新窗口
46 
47     while( GetMessage( &msg, NULL, 0, 0 ) )        //从消息队列中获取消息
48     {
49         TranslateMessage( &msg ) ;                 //将虚拟键消息转换为字符消息
50         DispatchMessage( &msg ) ;                  //分发到回调函数(过程函数)
51     }
52     return msg.wParam ;
53 }
54 
55 LRESULT CALLBACK WndProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam )
56 {
57     HDC hdc ;                //设备环境句柄
58     PAINTSTRUCT ps ;         //绘制结构
59     RECT rect;               //矩形结构
60 
61     switch( message )        //处理得到的消息
62     {
63     case WM_CREATE:          //窗口创建完成时发来的消息
64         MessageBox( hwnd, TEXT("窗口已创建完成!"), TEXT("我的窗口"), MB_OK | MB_ICONINFORMATION ) ;
65         return 0;
66 
67     case WM_PAINT:           //处理窗口区域无效时发来的消息
68         hdc = BeginPaint( hwnd, &ps ) ;
69         GetClientRect( hwnd, &rect ) ;
70         DrawText( hdc, TEXT( "Hello, 这是我自己的窗口!" ), -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER ) ;
71         EndPaint( hwnd, &ps ) ;
72         return 0 ;
73 
74     case WM_LBUTTONDOWN:     //处理鼠标左键被按下的消息
75         MessageBox( hwnd, TEXT("鼠标左键被按下。"), TEXT("单击"), MB_OK | MB_ICONINFORMATION ) ;
76         return 0;
77 
78     case WM_DESTROY:         //处理窗口关闭时的消息
79         MessageBox( hwnd, TEXT("关闭程序!"), TEXT("结束"), MB_OK | MB_ICONINFORMATION ) ;
80         PostQuitMessage( 0 ) ;
81         return 0;
82     }
83     return DefWindowProc( hwnd, message, wParam, lParam ) ;        //DefWindowProc处理我们自定义的消息处理函数没有处理到的消息
84 }

(1)窗口类对象wndclass的属性

wndclass.style = CS_HREDRAW | CS_VREDRAW ;                         //窗口样式
wndclass.lpszClassName = szAppName ;                               //窗口类名
wndclass.lpszMenuName = NULL ;                                     //窗口菜单:无
wndclass.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH) ;    //窗口背景颜色
wndclass.lpfnWndProc = WndProc ;                                   //窗口消息处理函数
wndclass.cbWndExtra = 0 ;                                          //窗口实例扩展:无
wndclass.cbClsExtra = 0 ;                                          //窗口类扩展:无
wndclass.hInstance = hInstance ;                                   //窗口实例句柄
wndclass.hIcon = LoadIcon( NULL, IDI_APPLICATION ) ;               //窗口最小化图标:使用缺省图标
wndclass.hCursor = LoadCursor( NULL, IDC_ARROW ) ;                 //窗口采用箭头光标

  

1>. wndclass.style = CS_HREDRAW | CS_VREDRAW ; 
  style属性决定着窗口的风格, 可以通过C语言的或运算组合出不同风格类型的窗口, 在WINUSER.H头文件中定义着这些标识符以及其值, 所有的前缀为CS_的标识符如下:
 * Class styles
#define CS_VREDRAW          0x0001
#define CS_HREDRAW          0x0002
#define CS_DBLCLKS          0x0008
#define CS_OWNDC            0x0020
#define CS_CLASSDC          0x0040
#define CS_PARENTDC         0x0080
#define CS_NOCLOSE          0x0200
#define CS_SAVEBITS         0x0800
#define CS_BYTEALIGNCLIENT  0x1000
#define CS_BYTEALIGNWINDOW  0x2000
#define CS_GLOBALCLASS      0x4000
#define CS_IME              0x00010000
2>. wndclass.lpszClassName = szAppName ;
  赋予窗口一个名称, 可以使用ASCII版本的字符串也可以使用Unicode版本的字符串, 需要注意的是, 这里的窗口名称并不是指窗口标题。
3>. wndclass.lpszMenuName = NULL ; 
  指定窗口类的菜单, 由于我们这个窗口没有使用菜单, 所以为NULL,
4>. wndclass.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH) ;
  窗口的背景颜色, 这里使用的是以白色作为填充, 填充白色这是常见的做法, 如果你愿意, 也可以填充为其他的一些样式, 这里是一些样式的标识符:
#define WHITE_BRUSH         0
#define LTGRAY_BRUSH        1
#define GRAY_BRUSH          2
#define DKGRAY_BRUSH        3
#define BLACK_BRUSH         4
#define NULL_BRUSH          5
#define HOLLOW_BRUSH        NULL_BRUSH
#define WHITE_PEN           6
#define BLACK_PEN           7
#define NULL_PEN            8
#define OEM_FIXED_FONT      10
#define ANSI_FIXED_FONT     11
#define ANSI_VAR_FONT       12
#define SYSTEM_FONT         13
#define DEVICE_DEFAULT_FONT 14
#define DEFAULT_PALETTE     15
#define SYSTEM_FIXED_FONT   16
5>. wndclass.lpfnWndProc = WndProc ; 
  将窗口的消息处理函数设置为我们自定义的WndProc函数。
6>. wndclass.cbWndExtra = 0 ; 
7>. wndclass.cbClsExtra = 0 ;
  这两个属性用来维护结构中预留的一些额外空间, 程序可以根据需要要使用这些额外空间, 通过匈牙利命名的cbClsExtra、cbWndExtra中的cb可以知道, 这些成员表示一个"字节数", 由于我们这个窗口没有使用到额外空间, 所以将这个两个属性赋值为0;
8>. wndclass.hInstance = hInstance ;
  表示应用程序的实例句柄,  hInstance的来源是WinMain的一个参数;
9>. wndclass.hIcon = LoadIcon( NULL, IDI_APPLICATION ) ;
  加载一个位图作为程序标题栏最左侧的小图标, 我们这里加载了一个系统的默认图标, 后面的学习这将会学习到如何从磁盘加载我们自定义的图标.
10>. wndclass.hCursor = LoadCursor( NULL, IDC_ARROW ) ; 
  与LoadIcon类似, 加载鼠标的指针位图;

  

 (2)注册窗口
    if( !RegisterClass( &wndclass ) )
    {    //注册窗口类, 如果注册失败弹出错误提示
        MessageBox( NULL, TEXT("窗口注册失败!"), TEXT("错误"), MB_OK | MB_ICONERROR ) ;
        return 0 ;
    }

  

  (3)创建窗口
 
 hwnd = CreateWindow(                   //创建窗口
                szAppName,                 //窗口类名
                TEXT("我的窗口"),           //窗口标题
                WS_OVERLAPPEDWINDOW,       //窗口的风格
                CW_USEDEFAULT,             //窗口初始显示位置x:使用缺省值
                CW_USEDEFAULT,             //窗口初始显示位置y:使用缺省值
                CW_USEDEFAULT,             //窗口的宽度:使用缺省值
                CW_USEDEFAULT,             //窗口的高度:使用缺省值
                NULL,                      //父窗口:无
                NULL,                      //子菜单:无
                hInstance,                 //该窗口应用程序的实例句柄 
                NULL                       //
            ) ;

  

1>.参数一: LPCTSTR  lpClassName
  参数LPCTSTR lpClassName,为窗口的名称, 我们需要传入的参数就是刚才我们在窗口类注册的窗口类名称, 这样使用CreateWindow建立的窗口就能与注册的窗口进行关联。 
2>. 参数三: DWORD dwStyle
  参数三为窗口的样式, 示例中创建的是一个普通的层叠窗口样式, WS_OVERLAPPEDWINDOW, 打开WINUSER.H头文件, 对于WS_OVERLAPPEDWINDOW是这样定义的:
#define WS_OVERLAPPEDWINDOW (WS_OVERLAPPED     |                              WS_CAPTION        |                              WS_SYSMENU        |                              WS_THICKFRAME     |                              WS_MINIMIZEBOX    |                              WS_MAXIMIZEBOX)

可以看出, WS_OVERLAPPEDWINDOW样式实际上是通过一些标识符通过或的组合, 此外我们还可以通过组合设计我们自己的样式, 这些标识符在WINUSER.H的定义如下:
#define WS_OVERLAPPED       0x00000000L            //产生一个层叠的窗口。一个层叠的窗口有一个标题条和一个边框。与WS_TILED风格相同。
#define WS_POPUP            0x80000000L            //创建一个弹出式窗口。该风格不能与WS_CHLD风格同时使用。
#define WS_CHILD            0x40000000L            //创建一个子窗口。这个风格不能与WS_POPUP风格合用。
#define WS_MINIMIZE         0x20000000L            //创建一个初始状态为最小化的窗口。仅与WS_OVERLAPPED风格一起使用。
#define WS_VISIBLE          0x10000000L            //创建一个最初可见的窗口。
#define WS_DISABLED         0x08000000L            //创建一个初始状态为禁止的窗口。
#define WS_CLIPSIBLINGS     0x04000000L            //排除子窗口之间的相对区域。
#define WS_CLIPCHILDREN     0x02000000L            //创建一个初始状态为禁止的子窗口。一个禁止状态的窗口不能接受来自用户的输入信息。
#define WS_MAXIMIZE         0x01000000L            //创建一个初始状态为最大化状态的窗口。 
#define WS_CAPTION          0x00C00000L            //创建一个有标题框的窗口(包括WS_BODER风格)。
#define WS_BORDER           0x00800000L            //创建一个单边框的窗口。 
#define WS_DLGFRAME         0x00400000L            //创建一个带对话框边框风格的窗口。这种风格的窗口不能带标题条。
#define WS_VSCROLL          0x00200000L            //创建一个有垂直滚动条的窗口。 
#define WS_HSCROLL          0x00100000L            //创建一个有水平滚动条的窗口。 
#define WS_SYSMENU          0x00080000L            //创建一个在标题条上带有窗口菜单的窗口,必须同时设定WS_CAPTION风格。
#define WS_THICKFRAME       0x00040000L            //创建一个具有可调边框的窗口,与WS_SIZEBOX风格相同。
#define WS_GROUP            0x00020000L            //指定一组控制的第一个控制。
#define WS_TABSTOP          0x00010000L            //创建一个控制,这个控制在用户按下Tab键时可以获得键盘焦点。按下Tab键后使键盘焦点转移到下一具有WS_TABSTOP风格的控制。
#define WS_MINIMIZEBOX      0x00020000L            //创建一个具有最小化按钮的窗口。
#define WS_MAXIMIZEBOX      0x00010000L            //创建一个具有最大化按钮的窗口。
#define WS_TILED            WS_OVERLAPPED          //产生一个层叠的窗口。一个层叠的窗口有一个标题和一个边框。与WS_OVERLAPPED风格相同。
#define WS_ICONIC           WS_MINIMIZE            //创建一个初始状态为最小化的窗口。仅与WS_OVERLAPPED风格一起使用。
#define WS_SIZEBOX          WS_THICKFRAME          //创建一个具有厚边框的窗口,可以通过厚边框来改变窗口大小。
#define WS_TILEDWINDOW      WS_OVERLAPPEDWINDOW    //创建一个具有WS_OVERLAPPED,WS_CAPTION,WS_SYSMENU,WS_THICKFRAME,WS_MINIMIZEBOX和WS_MAXIMIZEBOX风格的重叠式窗口。

  (4)窗口的显示、更新

    ShowWindow( hwnd, iCmdShow ) ;        //显示窗口
    UpdateWindow( hwnd ) ;                //更新窗口

  

ShowWindow函数的原型如下:
BOOL ShowWindow( HWND hWnd, int iCmdShow );
参数一为刚才通过CreateWindow函数窗口出的窗口句柄, 参数二为窗口的显示方式, 由WinMain函数的int iCmdShow接收该值, 常用的显示方式有:
SW_HIDE                        //隐藏窗口并激活其他窗口;
SW_MAXIMIZE                    //最大化;
SW_MINIMIZE                    //最小化指定的窗口并且激活在Z序中的下一个顶层窗口;
SW_RESTORE                     //激活并显示窗口。如果窗口最小化或最大化,则系统将窗口恢复到原来的尺寸和位置;
SW_SHOW                        //在窗口原来的位置以原来的尺寸激活和显示窗口;
SW_SHOWMAXIMIZED               //激活窗口并将其最大化;
SW_SHOWMINIMIZED               //激活窗口并将其最小化;
SW_SHOWMINNOACTIVE             //窗口最小化,激活窗口仍然维持激活状态;
SW_SHOWNA                      //以窗口原来的状态显示窗口。激活窗口仍然维持激活状态;
SW_SHOWNOACTIVATE              //以窗口最近一次的大小和状态显示窗口。激活窗口仍然维持激活状态;  
SW_SHOWNORMAL                  //激活并显示一个窗口。如果窗口被最小化或最大化,系统将其恢复到原来的尺寸和大小;
UpdateWindow函数的原型如下: BOOL UpdateWindow( HWND hWnd ); 该函数只有一个参数, 参数为需要更新的窗口句柄; 函数调用成功返回值为非0, 调用失败时返回值为0。

  (5)消息的转换、分发

 while( GetMessage( &msg, NULL, 0, 0 ) )        //从消息队列中获取消息
    {
        TranslateMessage( &msg ) ;                 //将虚拟键消息转换为字符消息
        DispatchMessage( &msg ) ;                  //分发到回调函数(过程函数)
    }
    return msg.wParam ;
}

  (6)消息处理函数

LRESULT CALLBACK WndProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam )
{
    HDC hdc ;                //设备环境句柄
    PAINTSTRUCT ps ;         //绘制结构
    RECT rect;               //矩形结构

    switch( message )        //处理得到的消息
    {
    case WM_CREATE:          //窗口创建完成时发来的消息
        MessageBox( hwnd, TEXT("窗口已创建完成!"), TEXT("我的窗口"), MB_OK | MB_ICONINFORMATION ) ;
        return 0;

    case WM_PAINT:           //处理窗口区域无效时发来的消息
        hdc = BeginPaint( hwnd, &ps ) ;
        GetClientRect( hwnd, &rect ) ;
        DrawText( hdc, TEXT( "Hello, 这是我自己的窗口!" ), -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER ) ;
        EndPaint( hwnd, &ps ) ;
        return 0 ;

    case WM_LBUTTONDOWN:     //处理鼠标左键被按下的消息
        MessageBox( hwnd, TEXT("鼠标左键被按下。"), TEXT("单击"), MB_OK | MB_ICONINFORMATION ) ;
        return 0;

    case WM_DESTROY:         //处理窗口关闭时的消息
        MessageBox( hwnd, TEXT("关闭程序!"), TEXT("结束"), MB_OK | MB_ICONINFORMATION ) ;
        PostQuitMessage( 0 ) ;
        return 0;
    }
    return DefWindowProc( hwnd, message, wParam, lParam ) ;        //DefWindowProc处理我们自定义的消息处理函数没有处理到的消息
}

  

 

 









以上是关于windows学习记录----hello world与窗口创建的主要内容,如果未能解决你的问题,请参考以下文章

java--ArrayList

QT手动编译(MinGW64) 学习记录

springboot docker 部署

Python基础之set集合与函数

if-case-循环语句

JS如何将变量作为一个对象的Key