Windows API 程式設計入門
-
- 1. Windows 程式内部運作原理簡述
- 2. 建立檔案
- 3. 開始編寫程式
-
-
- 3.1 頭檔案
- 3.2 WinMain函數(程式入口函數)
- 3.3 視窗過程函數
-
- 4. 運作結果截圖
- 5. 總結
學習目的:
- 了解 windows作業系統應用程式開發的基本概念,win32 API函數、消息與事件驅動
- 掌握WinMain函數的基本架構,視窗定義、視窗建立、消息循環及視窗過程函數
1. Windows 程式内部運作原理簡述
下面簡單講述一下Windows程式内部運作機制。一個Windows程式,是以消息為基礎,事務來推程序式的運作,這裡貼出一份Windows應用程式、作業系統、計算機硬體互相驅動的關系圖。
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIiclRnblN2XjlGcjAzNfRHLGZkRGZkRfJ3bs92YsYTMfVmepNHL90TUPhXTU5UerpWY650MMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2X0hXZ0xCMx81dvRWYoNHLrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zZuBnL0ITO3QzMwMjMxITOwAjMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
作業系統→輸出裝置:作業系統能操控計算機輸出裝置執行相應的功能,比如讓聲霸卡發生、顯示動畫等;
輸入裝置→作業系統:作業系統收到輸入裝置,如滑鼠、鍵盤發出的指令消息;
應用程式→作業系統:應用程式可以通過一些函數調用的形式通知作業系統讓聲霸卡發出何種聲音、顯示怎樣的畫面;
作業系統→應用程式:作業系統收到輸入裝置的指令後,将把指令壓入消息隊列中,應用程式從消息隊列中順序讀取并做處理。
這裡我們簡單了解一下就行了,我們Windows程式設計主要在應用程式上。
2. 建立檔案
實驗工具:Visual C++ 6.0
編譯環境:Windows 10
首先建立一個APP檔案。
然後在Projects目錄下選擇Win32 Application。
建立一個空檔案。
點選OK。
接下來就進入程式編寫界面了。
3. 開始編寫程式
一個簡單的Windows API 程式就隻有兩個函數,一個是程式入口函數,一個是視窗過程函數,下面我們來簡單闡述一下。
3.1 頭檔案
#include <windows.h>
#include <stdio.h>
3.2 WinMain函數(程式入口函數)
3.2.1 函數申明及參數
所有的C語言都會有一個函數入口,WinMain()函數有四個參數。
int WINAPI WinMain(
HINSTANCE hInstance, //目前視窗執行個體的句柄
HINSTANCE hPrevInstance, //先前視窗執行個體的句柄
LPSTR lpCmdLine, //指向字元串首位址的指針
int nCmdShow //表示指定視窗顯示狀态(最大、最小、隐藏顯示)
)
(注:固定格式,可以直接引用)
3.2.2 函數體
一個主函數内主要由五個部分。
-
設計一個視窗類
更改視窗的樣式可在該部分進行修改。
WNDCLASS wndcls; //視窗類申明變量wndcls
wndcls.style = CS_HREDRAW | CS_VREDRAW; //指定視窗類的類型:CS_HREDRAW(水準重畫)、CS_VREDRAW(垂直重畫)以達到視窗拉伸效果
wndcls.lpfnWndProc = WinSunProc; //将視窗過程函數指派給lpfnWndProc,讓作業系統來調用視窗過程函數,而不用我們自己調用
wndcls.cbClsExtra = 0; //給視窗設定額外的位元組,通常情況下設定為0
wndcls.cbWndExtra = 0; //給視窗設定附加記憶體,通常情況下設定為0
wndcls.hInstance = hInstance; //作業系統通過WinMain函數的形參hInstance,将視窗執行個體号指派給它
wndcls.hIcon = LoadIcon(NULL,IDI_APPLICATION); //圖示的句柄(視窗左上角的圖示),例:IDI_APPLICATION是一個标準的應用圖示
wndcls.hCursor = LoadCursor(NULL,IDC_ARROW); //光标的句柄(滑鼠),例:IDC_ARROW是一個标準箭頭光标
wndcls.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); //畫刷的句柄,例:WHITE_BRUSH設定了白色的背景圖
wndcls.lpszMenuName = NULL; //設定菜單的名字,本程式無菜單,是以設定為空
wndcls.lpszClassName = "Zcj2020"; //給視窗類設定名稱
- 注冊視窗類
- 建立視窗
HWND hwnd; //定義一個視窗句柄(辨別)
hwnd = CreateWindow("Zcj2020","重慶交通大學",WS_OVERLAPPEDWINDOW,
0,10,600,400,NULL,NULL,hInstance,NULL);
//CreateWindow函數參數解析(順序不可變):
//"Zcj2020":視窗類名(基于注冊後的視窗類名)
//"重慶交通大學":視窗标題欄的名稱
//WS_OVERLAPPEDWINDOW:視窗的類型
//0:視窗初始位置的橫坐标
//10:視窗初始位置的縱坐标
//600:視窗初始化後的寬
//400:視窗初始化後的高
//NULL:指定父視窗的句柄,本程式隻有一個視窗,是以設定為NULL
//NULL:菜單的句柄,本程式無菜單,是以設定為NULL
//hInstance:執行個體号
//NULL:WM_CREATE消息的附加參數指針,本程式用不上,是以設定為NULL
- 顯示及更新視窗
ShowWindow(hwnd,SW_SHOWNORMAL); //SW_SHOWNORMAL指的視窗初始正常顯示,此外還有最大化、最小化顯示,這裡不做贅述
UpdateWindow(hwnd); //更新視窗
-
消息循環體
GetMessage()函數從消息隊列中取出消息
MSG msg;
while(GetMessage(&msg,NULL,0,0))
{
TranslateMessage(&msg); //轉換(翻譯)消息并壓入消息隊列中
DispatchMessage(&msg); //将消息路由給作業系統,作業系統再調用視窗過程函數
}
return 0;
3.3 視窗過程函數
函數申明及參數
程式作出反應的函數,共4個參數。
//格式一定,參數類型不能更改,函數名、參數名可更改
LRESULT CALLBACK WinSunProc(
HWND hwnd, //視窗的句柄
UINT uMsg, //消息的辨別
WPARAM wParam, //附加參數
LPARAM lParam //附加參數
)
(注:格式一定,可直接引用)
函數體
{
switch(uMsg)
{
case WM_CHAR: //使用者按下鍵盤上的某個按鍵,并彈窗提示
char szChar[20];
sprintf(szChar,"char is %d",wParam);
MessageBox(hwnd,szChar,"提示",MB_OK);
break;
case WM_LBUTTONDOWN: //使用者按下滑鼠左鍵,彈窗提示并列印在視窗内
MessageBox(hwnd,"mouse clicked","提示",MB_OK);
HDC hdc;
hdc = GetDC(hwnd);
TextOut(hdc,0,50,"計算機左鍵已按下",strlen("計算機左鍵已按下")); //0和50是基于視窗而列印的位置
ReleaseDC(hwnd,hdc); //若不釋放,則會造成記憶體洩露!
break;
case WM_PAINT: //視窗重繪(視窗水準、豎直發生變化時都會發生視窗重繪)
HDC hDC;
PAINTSTRUCT ps;
hDC = BeginPaint(hwnd,&ps);
TextOut(hDC,0,0,"視窗重繪",strlen("視窗重繪")); //列印文本
EndPaint(hwnd,&ps); //注意及時結束重繪!
break;
case WM_CLOSE: //點選關閉按鈕時,做出反應
if(IDYES == MessageBox(hwnd,"是否真的結束?","提示",MB_YESNO))
{
DestroyWindow(hwnd); //銷毀視窗
}
break;
case WM_DESTROY: //視窗銷毀時,接收到銷毀消息
PostQuitMessage(0); //結束程式
break;
default:
return DefWindowProc(hwnd,uMsg,wParam,lParam); //對不感興趣的消息進行預設處理(注:該部分不可以删除,否則視窗不能正常顯示)
}
return 0;
}
4. 運作結果截圖
最後直接貼上完整的代碼。
#include <windows.h>
#include <stdio.h>
LRESULT CALLBACK WinSunProc(
HWND hwnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam
);
int WINAPI WinMain(
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow
)
{
WNDCLASS wndcls;
wndcls.style = CS_HREDRAW | CS_VREDRAW;
wndcls.lpfnWndProc = WinSunProc;
wndcls.cbClsExtra = 0;
wndcls.cbWndExtra = 0;
wndcls.hInstance = hInstance;
wndcls.hIcon = LoadIcon(NULL,IDI_APPLICATION);
wndcls.hCursor = LoadCursor(NULL,IDC_ARROW);
wndcls.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wndcls.lpszMenuName = NULL;
wndcls.lpszClassName = "Zcj2020";
RegisterClass(&wndcls);
HWND hwnd;
hwnd = CreateWindow("Zcj2020","重慶交通大學",WS_OVERLAPPEDWINDOW,
0,10,600,400,NULL,NULL,hInstance,NULL);
ShowWindow(hwnd,SW_SHOWNORMAL);
UpdateWindow(hwnd);
MSG msg;
while(GetMessage(&msg,NULL,0,0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
LRESULT CALLBACK WinSunProc(
HWND hwnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam
)
{
switch(uMsg)
{
case WM_CHAR:
char szChar[20];
sprintf(szChar,"char is %d",wParam);
MessageBox(hwnd,szChar,"提示",MB_OK);
break;
case WM_LBUTTONDOWN:
MessageBox(hwnd,"mouse clicked","提示",MB_OK);
HDC hdc;
hdc = GetDC(hwnd);
TextOut(hdc,0,50,"計算機左鍵已按下",strlen("計算機左鍵已按下"));
ReleaseDC(hwnd,hdc);
break;
case WM_PAINT:
HDC hDC;
PAINTSTRUCT ps;
hDC = BeginPaint(hwnd,&ps);
TextOut(hDC,0,0,"視窗重繪",strlen("視窗重繪"));
EndPaint(hwnd,&ps);
break;
case WM_CLOSE:
if(IDYES == MessageBox(hwnd,"是否真的結束?","提示",MB_YESNO))
{
DestroyWindow(hwnd);
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd,uMsg,wParam,lParam);
}
return 0;
}
程式運作開始
按下鍵盤的字母,顯示出的數字是字母的ASCLL碼
點選滑鼠左鍵
結束程式
最後程式關閉。
5. 總結
第一次寫部落格,有什麼不足可以賜教一下,如有幫到您的地方,不勝榮幸。
最後我推薦一本書——《深入淺出MFC_簡體版》,裡面第一章講述的就是Windows API程式設計,以下是書的電子書連結位址。
連結:https://pan.baidu.com/s/1PIzRAuG0EKN6tAlyAY2LyQ
提取碼:fjbo