了解窗口 每個GUI應用程序至少要創建一個窗口,稱為主窗口。每個窗口都在顯示輸出和從用戶取得輸入方面起著一定的作用。 窗口客戶區是應用程序顯示輸出的部分。應用程序必須提供一個稱為窗口函數的回調函數來處理窗口的輸入,向客戶區顯示輸出。 第一個窗口程序
int APIENTRY
WinMain ( HINSTANCE hInstance
, HINSTANCE hPrevInstance
, LPSTR lpCmdLine
, int nCmdShow
)
GUI應用程序的入口函數是WinMain,這是一個自定義的回調函數。
APIENTRY的宏定義是__stdcall
hInstance
= ( HINSTANCE
) GetModuleHandle ( NULL ) ;
參數為
NULL 時,返回可執行文件所在模塊的模塊句柄,而不管是在哪個模塊中做調用的。
int MessageBox ( HWND hWnd
, LPCTSTR lpText
, LPCTSTR lpCaption
, UINT uType
) ;
返回值:
IDOK、IDYES、IDNO、IDCANCEL、IDABORT、IDRETRY、IDIGNORE等
MessageBox中的uType參數
示例:簡單的win32
#include "stdafx.h" int APIENTRY
WinMain ( HINSTANCE hInstance
, HINSTANCE hPrevInstance
, LPSTR lpCmdLine
, int nCmdShow
)
{ MessageBox ( NULL , "Hello,Win32 Application" , "04Win32AppDemo" , MB_OK
) ; MessageBox ( NULL , "Hello,Win32 Application" , "04Win32AppDemo" , MB_YESNOCANCEL
| MB_ICONQUESTION
| MB_DEFBUTTON3
) return 0 ;
}
windows消息驅動 鼠標或鍵盤在桌面操作時,windows會源源不段地向程序發送消息,操作這個過程的函數為窗口函數。原型如下:
LRESULT CALLBACK
WindowProc ( HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
) ;
CALLBACK 宏定義是__stdcall
uMsg
: 消息ID號,諸如MessageBox中的IDYES等等
wParam和lParam是消息ID的附加參數
#include "stdafx.h"
#include "windows.h"
#include "stdio.h" int main ( int argc
, char * argv
[ ] )
{ HWND hWnd
= FindWindow ( NULL , "無標題 - 記事本" ) ; if ( hWnd
!= NULL ) { SendMessage ( hWnd
, WM_CLOSE
, 0 , 0 ) ; } return 0 ;
}
桌面顯示一個窗口的具體步驟:
注冊窗口類(RegisterClassEx) 創建窗口 (CreateWindowEx) 在桌面顯示窗口 (ShowWindow) 更新窗口客戶區(UpdateWindow) 進入無限的消息循環處理 獲取消息GetMessage DispatchMessage 消息處理MainWndProc函數
示例:最簡單的windows程序
#include "stdafx.h"
#include "windows.h"
#include "stdio.h" LRESULT CALLBACK
MainWndProc ( HWND
, UINT
, WPARAM
, LPARAM
) ; int APIENTRY
WinMain ( HINSTANCE hInstance
, HINSTANCE hPrevInstance
, LPSTR lpCmdLine
, int nCmdShow
)
{ char szClassName
[ ] = "MainClass" ; WNDCLASSEX wndclass
; wndclass
. cbSize
= sizeof ( wndclass
) ; wndclass
. style
= CS_HREDRAW
| CS_VREDRAW
; wndclass
. lpfnWndProc
= MainWndProc
; wndclass
. cbClsExtra
= 0 ; wndclass
. cbWndExtra
= 0 ; wndclass
. hInstance
= hInstance
; wndclass
. hIcon
= LoadIcon ( NULL , IDI_APPLICATION
) ; wndclass
. hCursor
= LoadCursor ( NULL , IDC_ARROW
) ; wndclass
. hbrBackground
= ( HBRUSH
) GetStockObject ( WHITE_BRUSH
) ; wndclass
. lpszMenuName
= NULL ; wndclass
. lpszClassName
= szClassName
; wndclass
. hIconSm
= NULL ; RegisterClassEx ( & wndclass
) ; HWND hwnd
= CreateWindowEx ( 0 , szClassName
, "My first Window!" , WS_OVERLAPPEDWINDOW
, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, NULL , NULL , hInstance
, NULL ) ; if ( hwnd
== NULL ) { MessageBox ( NULL , "創建窗口出錯!" , "error" , MB_OK
) ; return - 1 ; } ShowWindow ( hwnd
, nCmdShow
) ; UpdateWindow ( hwnd
) ; MSG msg
; while ( GetMessage ( & msg
, NULL , 0 , 0 ) ) { TranslateMessage ( & msg
) ; DispatchMessage ( & msg
) ; } return msg
. wParam
;
} LRESULT CALLBACK
MainWndProc ( HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
{ char szText
[ ] = "最簡單的窗口程序" ; switch ( message
) { case WM_PAINT
: { HDC hdc
; PAINTSTRUCT ps
; hdc
= BeginPaint ( hwnd
, & ps
) ; TextOut ( hdc
, 10 , 10 , szText
, strlen ( szText
) ) ; EndPaint ( hwnd
, & ps
) ; return 0 ; } case WM_DESTROY
: PostQuitMessage ( 0 ) ; return 0 ; } return DefWindowProc ( hwnd
, message
, wParam
, lParam
) ; }
使用資源 資源是一些二進制數據,它能夠添加到基于窗口的應用程序的可執行文件中。資源的源文件是以.rc為擴展名的腳本文件。 在原來的工程下新建一個資源腳本,命令為resource 程序左側會生成一個resource.rc文件和resource.h文件(隱藏,得去工程目錄下查找)
IDI_ICON1和IDR_TYPER可以自定義,且在函數中會使用到
然后右鍵resource.rc文件,選擇插入圖標和菜單
插入菜單舉例右鍵打開: 里面的內容通過修改標明項即可自定義內容 ID可以設置為ID_FILE_EXIT
#include "stdafx.h"
#include "windows.h"
#include "stdio.h"
#include "resource.h" LRESULT CALLBACK
MainWndProc ( HWND
, UINT
, WPARAM
, LPARAM
) ; int APIENTRY
WinMain ( HINSTANCE hInstance
, HINSTANCE hPrevInstance
, LPSTR lpCmdLine
, int nCmdShow
)
{ char szClassName
[ ] = "MainClass" ; WNDCLASSEX wndclass
; wndclass
. cbSize
= sizeof ( wndclass
) ; wndclass
. style
= CS_HREDRAW
| CS_VREDRAW
; wndclass
. lpfnWndProc
= MainWndProc
; wndclass
. cbClsExtra
= 0 ; wndclass
. cbWndExtra
= 0 ; wndclass
. hInstance
= hInstance
; wndclass
. hIcon
= LoadIcon ( hInstance
, ( LPSTR
) IDI_ICON1
) ; wndclass
. hCursor
= LoadCursor ( NULL , IDC_ARROW
) ; wndclass
. hbrBackground
= ( HBRUSH
) GetStockObject ( WHITE_BRUSH
) ; wndclass
. lpszMenuName
= ( LPSTR
) IDR_TYPER
; wndclass
. lpszClassName
= szClassName
; wndclass
. hIconSm
= NULL ; RegisterClassEx ( & wndclass
) ; HWND hwnd
= CreateWindowEx ( 0 , szClassName
, "My first Window!" , WS_OVERLAPPEDWINDOW
, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, NULL , NULL , hInstance
, NULL ) ; if ( hwnd
== NULL ) { MessageBox ( NULL , "創建窗口出錯!" , "error" , MB_OK
) ; return - 1 ; } ShowWindow ( hwnd
, nCmdShow
) ; UpdateWindow ( hwnd
) ; MSG msg
; while ( GetMessage ( & msg
, NULL , 0 , 0 ) ) { TranslateMessage ( & msg
) ; DispatchMessage ( & msg
) ; } return msg
. wParam
;
} LRESULT CALLBACK
MainWndProc ( HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
{ char szText
[ ] = "最簡單的窗口程序" ; switch ( message
) { case WM_PAINT
: { HDC hdc
; PAINTSTRUCT ps
; hdc
= BeginPaint ( hwnd
, & ps
) ; TextOut ( hdc
, 10 , 10 , szText
, strlen ( szText
) ) ; EndPaint ( hwnd
, & ps
) ; return 0 ; } case WM_COMMAND
: switch ( LOWORD ( wParam
) ) { case ID_FILE_EXIT
: SendMessage ( hwnd
, WM_CLOSE
, 0 , 0 ) ; break ; } return 0 ; case WM_CLOSE
: return 0 ; case WM_DESTROY
: PostQuitMessage ( 0 ) ; return 0 ; } return DefWindowProc ( hwnd
, message
, wParam
, lParam
) ; }
生成的圖標和菜單如下所示:圖標是瞎畫的
單擊菜單會發送WM_COMMAND消息,而wParam低字節包含了用戶單擊菜單的ID號
接受鍵盤輸入消息 按下一個鍵時,windows會獲得窗口消息隊列中傳遞的WM_KEYDOWN或WM_SYSKEYDOWN消息。釋放這個鍵時,會產生WM_KEYUP或WM_SYSTEMKEYUP消息。 wParam wParam包含敲擊鍵的虛擬鍵碼,也包含按鍵的ANSI碼,比如敲“A”鍵,窗口會受到3個消息:
WM_KETDOWN lParam的含義為虛擬鍵碼“A”(0x41)
WM_CHAR lParam的含義為虛擬鍵碼“a”(0x61)
WM_KEYUP lParam的含義為虛擬鍵碼“A”(0x41)
示例:打字程序
#include "stdafx.h"
#include "windows.h"
#include "stdio.h"
#include "resource.h"
#include <string>LRESULT CALLBACK MainWndProc(HWND,UINT,WPARAM,LPARAM);int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)
{char szClassName[] = "MainClass";WNDCLASSEX wndclass;//用于描述主窗口的參數填充WNDCLASSEX結構wndclass.cbSize = sizeof(wndclass); //結構的大小wndclass.style = CS_HREDRAW | CS_VREDRAW; //指定如果大小改變就重畫wndclass.lpfnWndProc = MainWndProc; //窗口函數指針wndclass.cbClsExtra = 0; //沒有額外的類內存wndclass.cbWndExtra = 0; //沒有額外的窗口內存wndclass.hInstance = hInstance; //實例句柄wndclass.hIcon = LoadIcon(hInstance,(LPSTR)IDI_ICON1); //使用預定義圖標wndclass.hCursor = LoadCursor(NULL,IDC_ARROW); //使用預定義光標wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); //使用白色背景畫刷wndclass.lpszMenuName = (LPSTR)IDR_TYPER; //指定自定義的菜單wndclass.lpszClassName = szClassName; //窗口類的名稱wndclass.hIconSm = NULL; //沒有類的小圖標//注冊這個窗口類RegisterClassEx(&wndclass);//創建主窗口HWND hwnd = CreateWindowEx(0, //dwExSytle,擴展szClassName, //lpClassName,窗口類名"My first Window!", //lpWindowName,標題WS_OVERLAPPEDWINDOW, //dwStyle,窗口風格CW_USEDEFAULT, //X,初始化X坐標CW_USEDEFAULT, //y,初始化Y坐標CW_USEDEFAULT, //nWidth,寬度CW_USEDEFAULT, //nHeight,高度NULL, //hWindParent 父窗口句柄NULL, //hMenu 菜單句柄hInstance, //hInstance,程序實例句柄NULL //lpParam,用戶數據 );if(hwnd == NULL){MessageBox(NULL,"創建窗口出錯!","error",MB_OK);return -1;}//顯示窗口,刷新窗口客戶區ShowWindow(hwnd,nCmdShow);UpdateWindow(hwnd);//從消息隊列中取出消息,交給窗口函數處理,直到GetMessage返回FALSE,結束消息循環MSG msg;while(GetMessage(&msg,NULL,0,0)){//轉化為鍵盤消息TranslateMessage(&msg);//將消息發送到相應的窗口函數DispatchMessage(&msg);}//當GetMessage返回FALSE時程序結束return msg.wParam;
}LRESULT CALLBACK MainWndProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
{//str對象用于保存窗口客戶區顯示的字符串//為了使用string類,包含頭文件#include <string>static std::string str;char szText[] = "最簡單的窗口程序";switch(message){case WM_CREATE:{//設置窗口的標題SetWindowText(hwnd,"最簡陋的打字程序");return 0;}case WM_PAINT: //窗口客戶區需要重畫{HDC hdc;PAINTSTRUCT ps;//使無效的客戶區變的有效,并取得設備環境句柄hdc = BeginPaint(hwnd,&ps);//顯示文字TextOut(hdc,0,0,str.c_str(),str.length());EndPaint(hwnd,&ps);return 0;}case WM_CHAR:{//保存ANSI碼str = str + char(wParam);//使整個客戶區無效InvalidateRect(hwnd,NULL,0);return 0;}case WM_COMMAND:switch(LOWORD(wParam)){case ID_FILE_EXIT://向hwnd指定的窗口發送一個WM_CLOSE消息SendMessage(hwnd,WM_CLOSE,0,0);break;}return 0;//case WM_CLOSE: //任務管理器還是能干掉// return 0; case WM_DESTROY: //正在銷毀窗口//向消息隊列發送一個WM_QUIT消息,促使GetMessage函數返回0,結束消息循環PostQuitMessage(0);return 0;}//我們不處理的消息交給系統做默認處理return DefWindowProc(hwnd,message,wParam,lParam);}
按下彈起雙擊 左鍵 WM_LBUTTONDOWN WM_LBUTTONUP WM_LBUTTONBLCLK 中鍵 WM_MBUTTONDOWN WM_MBUTTONUP WM_MBUTTONBLCLK 右鍵 WM_RBUTTONDOWN WM_RBUTTONUP WM_RBUTTONBLCLK
發送這些消息時,lParam包含了客戶區坐標信息
xPos
= LOWORD ( lParam
) ;
yPos
= HIWORD ( lParam
) ;
轉化為屏幕的坐標信息
BOOL
ClientToScreen ( HWND hWnd
, LPPOINT lpPoint
) ;
BOOL
ScreenToClient ( HWND hWnd
, LPPOINT lpPoint
) ;
MK_LBUTTON 左鍵按下
MK_MBUTTON 中間的鍵按下
MK_RBUTTON 右鍵按下
MK_SHIFT
< Shift
> 鍵按下
MK_CONTROL
< Ctrl
> 鍵按下
#include "stdafx.h"
#include "windows.h"
#include "stdio.h"
#include "resource.h"
#include <string>LRESULT CALLBACK MainWndProc(HWND,UINT,WPARAM,LPARAM);int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)
{char szClassName[] = "MainClass";WNDCLASSEX wndclass;//用于描述主窗口的參數填充WNDCLASSEX結構wndclass.cbSize = sizeof(wndclass); //結構的大小wndclass.style = CS_HREDRAW | CS_VREDRAW; //指定如果大小改變就重畫wndclass.lpfnWndProc = MainWndProc; //窗口函數指針wndclass.cbClsExtra = 0; //沒有額外的類內存wndclass.cbWndExtra = 0; //沒有額外的窗口內存wndclass.hInstance = hInstance; //實例句柄wndclass.hIcon = LoadIcon(hInstance,(LPSTR)IDI_ICON1); //使用預定義圖標wndclass.hCursor = LoadCursor(NULL,IDC_ARROW); //使用預定義光標wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); //使用白色背景畫刷wndclass.lpszMenuName = (LPSTR)IDR_TYPER; //指定自定義的菜單wndclass.lpszClassName = szClassName; //窗口類的名稱wndclass.hIconSm = NULL; //沒有類的小圖標//注冊這個窗口類RegisterClassEx(&wndclass);//創建主窗口HWND hwnd = CreateWindowEx(0, //dwExSytle,擴展szClassName, //lpClassName,窗口類名"My first Window!", //lpWindowName,標題WS_OVERLAPPEDWINDOW, //dwStyle,窗口風格CW_USEDEFAULT, //X,初始化X坐標CW_USEDEFAULT, //y,初始化Y坐標CW_USEDEFAULT, //nWidth,寬度CW_USEDEFAULT, //nHeight,高度NULL, //hWindParent 父窗口句柄NULL, //hMenu 菜單句柄hInstance, //hInstance,程序實例句柄NULL //lpParam,用戶數據 );if(hwnd == NULL){MessageBox(NULL,"創建窗口出錯!","error",MB_OK);return -1;}//顯示窗口,刷新窗口客戶區ShowWindow(hwnd,nCmdShow);UpdateWindow(hwnd);//從消息隊列中取出消息,交給窗口函數處理,直到GetMessage返回FALSE,結束消息循環MSG msg;while(GetMessage(&msg,NULL,0,0)){//轉化為鍵盤消息TranslateMessage(&msg);//將消息發送到相應的窗口函數DispatchMessage(&msg);}//當GetMessage返回FALSE時程序結束return msg.wParam;
}LRESULT CALLBACK MainWndProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
{//str對象用于保存窗口客戶區顯示的字符串//為了使用string類,包含頭文件#include <string>static std::string str;char szText[] = "最簡單的窗口程序";switch(message){case WM_CREATE:{//設置窗口的標題SetWindowText(hwnd,"最簡陋的打字程序");return 0;}case WM_PAINT: //窗口客戶區需要重畫{HDC hdc;PAINTSTRUCT ps;//使無效的客戶區變的有效,并取得設備環境句柄hdc = BeginPaint(hwnd,&ps);//顯示文字TextOut(hdc,0,0,str.c_str(),str.length());EndPaint(hwnd,&ps);return 0;}case WM_CHAR:{//保存ANSI碼str = str + char(wParam);//使整個客戶區無效InvalidateRect(hwnd,NULL,0);return 0;}case WM_COMMAND:switch(LOWORD(wParam)){case ID_FILE_EXIT://向hwnd指定的窗口發送一個WM_CLOSE消息SendMessage(hwnd,WM_CLOSE,0,0);break;}return 0;case WM_LBUTTONDOWN: //用戶單擊鼠標左鍵{char szPoint[56];//保存坐標信息wsprintf(szPoint,"X = %d,Y = %d",LOWORD(lParam),HIWORD(lParam));str = szPoint;if(wParam & MK_SHIFT)str = str+" Shift Key is down";InvalidateRect(hwnd,NULL,1);return 0; }//case WM_CLOSE: //任務管理器還是能干掉// return 0; case WM_DESTROY: //正在銷毀窗口//向消息隊列發送一個WM_QUIT消息,促使GetMessage函數返回0,結束消息循環PostQuitMessage(0);return 0;}//我們不處理的消息交給系統做默認處理return DefWindowProc(hwnd,message,wParam,lParam);}
#include "stdafx.h"
#include "windows.h"
#include "stdio.h"
#include "resource.h"
#include <string> LRESULT CALLBACK
MainWndProc ( HWND
, UINT
, WPARAM
, LPARAM
) ; int APIENTRY
WinMain ( HINSTANCE hInstance
, HINSTANCE hPrevInstance
, LPSTR lpCmdLine
, int nCmdShow
)
{ char szClassName
[ ] = "MainClass" ; WNDCLASSEX wndclass
; wndclass
. cbSize
= sizeof ( wndclass
) ; wndclass
. style
= CS_HREDRAW
| CS_VREDRAW
; wndclass
. lpfnWndProc
= MainWndProc
; wndclass
. cbClsExtra
= 0 ; wndclass
. cbWndExtra
= 0 ; wndclass
. hInstance
= hInstance
; wndclass
. hIcon
= LoadIcon ( hInstance
, ( LPSTR
) IDI_ICON1
) ; wndclass
. hCursor
= LoadCursor ( NULL , IDC_ARROW
) ; wndclass
. hbrBackground
= ( HBRUSH
) GetStockObject ( WHITE_BRUSH
) ; wndclass
. lpszMenuName
= ( LPSTR
) IDR_TYPER
; wndclass
. lpszClassName
= szClassName
; wndclass
. hIconSm
= NULL ; RegisterClassEx ( & wndclass
) ; HWND hwnd
= CreateWindowEx ( 0 , szClassName
, "My first Window!" , WS_OVERLAPPEDWINDOW
, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, NULL , NULL , hInstance
, NULL ) ; if ( hwnd
== NULL ) { MessageBox ( NULL , "創建窗口出錯!" , "error" , MB_OK
) ; return - 1 ; } ShowWindow ( hwnd
, nCmdShow
) ; UpdateWindow ( hwnd
) ; MSG msg
; while ( GetMessage ( & msg
, NULL , 0 , 0 ) ) { TranslateMessage ( & msg
) ; DispatchMessage ( & msg
) ; } return msg
. wParam
;
} LRESULT CALLBACK
MainWndProc ( HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
{ static std
: : string str
; char szText
[ ] = "最簡單的窗口程序" ; switch ( message
) { case WM_CREATE
: { SetWindowText ( hwnd
, "最簡陋的打字程序" ) ; return 0 ; } case WM_PAINT
: { HDC hdc
; PAINTSTRUCT ps
; hdc
= BeginPaint ( hwnd
, & ps
) ; SetTextColor ( hdc
, RGB ( 255 , 0 , 0 ) ) ; SetBkColor ( hdc
, GetSysColor ( COLOR_3DFACE
) ) ; TextOut ( hdc
, 0 , 0 , str
. c_str ( ) , str
. length ( ) ) ; EndPaint ( hwnd
, & ps
) ; return 0 ; } case WM_CHAR
: { str
= str
+ char ( wParam
) ; InvalidateRect ( hwnd
, NULL , 0 ) ; return 0 ; } case WM_COMMAND
: switch ( LOWORD ( wParam
) ) { case ID_FILE_EXIT
: SendMessage ( hwnd
, WM_CLOSE
, 0 , 0 ) ; break ; } return 0 ; case WM_LBUTTONDOWN
: { char szPoint
[ 56 ] ; wsprintf ( szPoint
, "X = %d,Y = %d" , LOWORD ( lParam
) , HIWORD ( lParam
) ) ; str
= szPoint
; if ( wParam
& MK_SHIFT
) str
= str
+ " Shift Key is down" ; InvalidateRect ( hwnd
, NULL , 1 ) ; return 0 ; } case WM_DESTROY
: PostQuitMessage ( 0 ) ; return 0 ; } return DefWindowProc ( hwnd
, message
, wParam
, lParam
) ; }
總結
以上是生活随笔 為你收集整理的3.windows图形界面 的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔 網站內容還不錯,歡迎將生活随笔 推薦給好友。