C++使用代碼創建一個Windows桌面應用程序


WinMain函數

Windows應用程序的唯一程序入口。

函數原型

1 int WINAPI WinMain
2 {
3     HINSTANCE hInstancem
4     HINSTANCE hPreInstance,
5     LPSTR lpCmdLine,
6     int nCmdShow 
7 }

WINAPI定義如下

#define WINAPI _stdcall

 

_stdcall是一個函數調用約定,除此之外,還有__cdeclfastcallthiscallnaked call等函數調用約定。

_stdcall調用約定又稱Pascal調用約定,也是Pascal語言的調用約定。它使用的方式為:

1 int __stdcall sum(int a,int b);

__stdcall:函數的多個參數由調用者按從右到左的順序壓入堆棧,被調用函數獲得參數的序列是從左到右的的;清理堆棧的工作由被調用函數負責。
在Visual C++中,常用宏WINAPICALLBACK來表示__stdcall調用約定。

更詳細的說明可以查看

https://docs.microsoft.com/en-us/cpp/cpp/stdcall?view=vs-2019

 

__cdecl(也可寫成_cdecl)調用約定又稱C調用約定,是C函數默認的調用約定,也是C++全局函數的默認調用約定,通常省略。

1 int sum(int a,int b);
2 int __cdecl sum(int a,int b);

__cdecl:函數的多個參數由調用者按從右向左的順序壓入堆棧,被調函數獲得參數的序列是從左到右的;清理堆棧的工作由調用者負責

更詳細的說明可以查看
https://docs.microsoft.com/en-us/cpp/cpp/cdecl?view=vs-2019

 

WinMain函數的各參數說明

hInstance

應用程序當前運行的實例的句柄,該句柄由Windows系統生成。

 

hPrevInstance

當前實例的前一個實例的句柄,在Win32環境下,該參數總是NULL,不再起作用

 

lpCmdLine

一個以空終止的字符串,代表傳遞給程序的命令行參數。

 

nCmdShow

指定窗口的顯示狀態

常用值如下

nCmdShow = 0;不顯示

nCmdShow = 1;正常顯示(默認)

nCmdShow = 2;最小化顯示

nCmdShow = 3;最大化顯示

 

使用代碼創建Windows程序的步驟

1、設計一個Windows類

2、在Windows系統中注冊Windows類

3、用該Windows類創建一個窗口

4、創建一個消息循環

5、創建一個窗口過程函數WndProc

 

一、設計Windows類

在創建一個窗口前,必須對窗口進行設計,指定窗口的屬性。系統已經定義了WNDCLASS結構用於描述待創建窗口的參數。

WNDCLASS聲明如下

 1 typedef struct tagWNDCLASSA {
 2   UINT      style;
 3   WNDPROC   lpfnWndProc;
 4   int       cbClsExtra;
 5   int       cbWndExtra;
 6   HINSTANCE hInstance;
 7   HICON     hIcon;
 8   HCURSOR   hCursor;
 9   HBRUSH    hbrBackground;
10   LPCSTR    lpszMenuName;
11   LPCSTR    lpszClassName;
12 } WNDCLASSA, *PWNDCLASSA, *NPWNDCLASSA, *LPWNDCLASSA;

下面介紹各參數

style

窗口樣式,可用值如下

CS_VREDRAW:垂直重繪,當窗口垂直方向上的高度發生變化時,將重新繪制整個窗口。如果沒有指定這一樣式,在垂直方向上調整窗口高度時,將不會重繪窗口。

CS_HREDRAW:水平重繪,當窗口水平方向上的寬度發生變化時,將重新繪制整個窗口。如果沒有指定這一樣式,在水平方向上調整窗口高度時,將不會重繪窗口。

CS_OWNDC:獨占設備描述表,為該類中的每個窗口分配一個單值的設備描述表。

CS_SAVEBITS:在一個窗口中保存用戶圖像,以便於在該窗口被遮住、移動時不必每次刷新屏幕。但是,這樣會占用更多的內存,並且比人工進行同樣操作時要慢得多。

CS_DBLCLKS:使窗口可以檢測到鼠標雙擊事件,當用戶在窗口中雙擊鼠標時,向窗口過程發送鼠標雙擊消息

CS_BYTEALLGNCLIENT:鼠標用戶區域按字節對齊顯示。

CS_BYTEALLGNWINDOW:鼠標用戶窗口按字節對齊顯示。

CS_PARENTDC:在父窗口中設定一個子窗口的剪切區,以便於子窗口能夠畫在父窗口中。

CS_NOCLOSE:系統菜單中沒有CLOSE菜單項,窗口沒有關閉按鈕。

lpfnWndProc

指向窗口過程函數的函數指針。窗口過程函數是一個回調函數,針對Windows的消息處理機制,窗口過程函數被調用的過程如下:

1、在設計窗口類的時候,將窗口過程函數的地址賦給lpfnWndProc成員變量

2、調用RegisterClass(&wndclass)注冊窗口類,系統就有了用戶編寫的窗口過程函數的地址

3、當應用程序接收到某一窗口的信息時,調用DispatchMessage(&msg)將消息回傳給系統。系統則利用先前注冊窗口類時得到的函數指針,調用窗口過程函數對消息進行處理

cbClsExtra

Windows系統為窗口類結構分配追加的額外字節數。一般為0

cbWndExtra

Windows系統為窗口實例分配或追加的額外字節數,一般為0。如果應用程序使用資源文件里的CLASS指令創建對話框,並用WNDCLASS結構注冊對話框框時,cbWndExtra必須設置成DLGWINDOWEXTRA

hInstance

包含窗口過程程序的實例句柄。一般直接賦WinMain()的hInstance即可

hIcon

窗口類的圖標資源。這個成員變量必須是一個圖標資源的句柄。可以使用LoadIcon()函數加載圖標,如果hIcon為NULL,窗口將使用系統提供的默認圖標

hCursor

窗口類的光標句柄。這個成員變量必須是一個光標資源的句柄。可以使用LoadCursor()函數加載光標。如果hCursor為NULL,應用程序必須在鼠標進入應用程序窗口時,明確設置光標的形狀

hbrBackground

窗口類的背景畫刷句柄。當窗口發生重繪時,系統使用這里指定的畫刷來填充窗口的背景。該成員可以指定為用於繪制背景的物理畫刷的句柄,也可以指定為標准的系統顏色值。如下:

BLACK_BRUSH 黑色

DKGRAY_BRUSH 深灰

GRAY_BRUSH 灰色

HOLLOW_BRUSH 空

LTGRAY_BRUSH 淺灰

NULL_BRUSH 等同於HOLLOW_BRUSH

WHITE_BRUSH 白色

BLACK_BRUSH 黑色

lpszMenuName

指向一個以空終止的字符串,該字符串描述菜單的資源名。若使用整數來標識菜單,需要用MAKEINTRESOURCE宏來進行轉換。如果lpszMenuName設置為NULL,那么基於窗口類創建的窗口將沒有默認菜單

lpszClassName

指向一個以空終止的字符串,該字符串描述窗口類的名字。這個類名可以是由RegisterClass或者RegisterClassEx注冊的名字,或者是任何預定義的控件類名

WNDCLASS使用實例如下

 1 WNDCLASS wc;
 2 
 3     wc.style          = CS_HREDRAW | CS_VREDRAW;
 4     wc.lpfnWndProc    = WndProc;
 5     wc.cbClsExtra     = 0;
 6     wc.cbWndExtra     = 0;
 7     wc.hInstance      = hInstance;
 8     wc.hIcon          = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_WINDOWSPROJECT1));
 9     wc.hCursor        = LoadCursor(nullptr, IDC_ARROW);
10     wc.hbrBackground  = (HBRUSH)(COLOR_WINDOW+1);
11     wc.lpszMenuName   = MAKEINTRESOURCEW(IDC_WINDOWSPROJECT1);
12     wc.lpszClassName  = szWindowClass;

 

二、注冊Windows類

Windows類設計完成時,需要調用RegisterClass()函數去注冊這個類,才可以創建該類型的窗口

1 ATOM RegisterClass(
2   const WNDCLASSA *lpWndClass
3 );

注冊代碼如下

if(!RegisterClass(&wc))
{
    return 0;
}

 

三、創建窗口

 使用CreateWindow函數創建窗口,如果函數調用成功,返回值為新窗口的句柄;如果調用失敗,返回值為NULL。可以使用GetLastError()函數獲取錯誤信息

 1 HWND CreateWindow( 
 2   LPCTSTR lpClassName, 
 3   LPCTSTR lpWindowName, 
 4   DWORD dwStyle, 
 5   int x, 
 6   int y, 
 7   int nWidth, 
 8   int nHeight, 
 9   HWND hWndParent, 
10   HMENU hMenu, 
11   HANDLE hInstance, 
12   PVOID lpParam 
13 ); 

lpClassName

指定窗口類的名稱,這個名稱就是WNDCLASSA中的lpszClassName。如果在調用CreateWindow函數之前,沒有調用RegisterClass函數注冊這個類,系統無法得知窗口的相關信息,窗口創建就會失敗。

lpWindowName

指定窗口名稱,如果指定了標題欄,那么這里指向的字符串就會顯示在標題欄上。

dwStyle

指定創建窗口的樣式,可以組合不同的窗口樣式

常量 說明
WS_CAPTION(0x00C00000L) 創建一個有標題欄的窗口
WS_SYSMENU(0x00080000L) 創建一個在標題欄上帶有系統菜單的窗口(需要和WS_CAPTION一起使用)
WS_MINIMIZEBOX(0x00020000L) 創建一個具有最小化按鈕的窗口(需要和WS_SYSMENU一起使用)
WS_MAXIMIZEBOX(0x00010000L) 創建一個具有最大化按鈕的窗口(需要和WS_SYSMENU一起使用)
WS_TILED(0x00000000L) 創建一個層疊的窗口,層疊的窗口有一個標題欄和一個邊框
WS_TILEDWINDOW 創建一個使用(WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX)樣式的層疊的窗口
WS_CHILD(0x40000000L) 創建窗口為子窗口,不能應用於彈出式窗口樣式
WS_OVERLAPPED 與WS_TILED樣式相同
WS_OVERLAPPEDWINDOW 創建一個使用(WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX)樣式的層疊的窗口
WS_EX_TOPMOST 創建一個始終置頂的窗口(不管窗口是否已經激活)  
WS_POPUP(0x80000000L) 創建一個彈出式窗口(不能與WS_CHILD一起使用)
WS_VISIBLE(0x10000000L) 創建一個初始狀態為可見的窗口(可以使用ShowWindow函數來控制顯示或隱藏窗口)
完整窗口樣式可以訪問:https://docs.microsoft.com/en-us/windows/win32/winmsg/window-styles

x

指定窗口左上角的x坐標

y

指定窗口左上角的y坐標

nWidth

以設備單元指定窗口的寬度 

nHeight

以設備單元指定窗口的高度

hWndParent

指定被創建窗口的父窗口的句柄。如果要創建一個子窗口,這里就需要提供父窗口的句柄。

hMenu

菜單句柄,指向附屬於該窗口的菜單

hInstance

WinMain函數中傳入的應用程序實例的句柄

lpParam

作為WM_CREATE消息的附加參數lParam傳入的數據指針。在創建多文檔界面的客戶窗口時,lpParam必須指向CLIENTCREATESTRUCT結構體。多數窗口將這個參數設置為NULL

 

CreateWindow示例代碼如下

HWND hwnd; 
 
    hwnd = CreateWindow( 
        "MainWClass",        
        "Test Window",           
        WS_OVERLAPPEDWINDOW, 
        0,      
        0,    
        CW_USEDEFAULT,       // 默認寬度
        CW_USEDEFAULT,       // 默認高度
        NULL,         // 沒有父窗體
        NULL,        // 沒有菜單
        hinstance,           
        NULL);      //沒有附加數據

 

四、顯示窗口

執行CreateWindow函數,窗體創建成功之后,需要調用ShowWindow函數把窗口顯示在桌面上

BOOL ShowWindow(HWND hWnd,int nCmdShow);

hWnd

CreateWindow創建窗口成功后返回的窗口句柄

nCmdShow

指示窗口顯示的狀態

常用的窗口顯示狀態如下

SW_HIDE: 隱藏窗口並激活其它窗口

SW_SHOW: 在窗口原來的位置以原來的尺寸激活並顯示窗口

SW_SHOWMAXIMIZED: 激活並以最大化顯示窗口

SW_SHOWMINIMIZED: 激活並最小化顯示窗口

SW_SHOWNORMAL 激活並顯示窗口。如果窗口是最大化或最小化的狀態,系統將其恢復到原來的尺寸和大小。應用程序在第一次顯示窗口時,應該使用這種狀態

 

未完


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM