視窗與訊息 (window and message)

22
視視視視視 視視視視視 (Window and Message) (Window and Message) 視視視視視

Upload: tamar

Post on 26-Jan-2016

71 views

Category:

Documents


2 download

DESCRIPTION

視窗與訊息 (Window and Message). 井民全製作. 建立自己的視窗. CreateWindow 函式就可以建立視窗 背景知識 子視窗 ( 控制項視窗 , 子視窗控制項 ) 選單按鈕 , 核取方塊 , 清單方塊 , 捲動列 , 文字輸入  都是 視窗 的一種. child window. Message 概念. Message: 視窗間使用 message 作通訊 程式建立的每個視窗都有一相關的 視窗訊息處理程式 Window class 標示了 視窗訊息的處理程式 - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: 視窗與訊息 (Window and Message)

視窗與訊息視窗與訊息(Window and Message)(Window and Message)

井民全製作

Page 2: 視窗與訊息 (Window and Message)

建立自己的視窗建立自己的視窗CreateWindow CreateWindow 函式就可以建立視窗函式就可以建立視窗背景知識背景知識– 子視窗 子視窗 (( 控制項視窗控制項視窗 ,, 子視窗控制項子視窗控制項 ))

選單按鈕選單按鈕 , , 核取方塊核取方塊 , , 清單方塊清單方塊 , , 捲動列捲動列 , , 文字文字輸入輸入

都是都是視窗視窗的一種的一種

child window

Page 3: 視窗與訊息 (Window and Message)

Message Message 概念概念Message: Message: 視窗間使用 視窗間使用 message message 作通訊作通訊

– 程式建立的每個視窗都有一相關的程式建立的每個視窗都有一相關的視窗訊息處理程式視窗訊息處理程式

– Window class Window class 標示了標示了視窗訊息的處理程式視窗訊息的處理程式 多個視窗可同屬一個 多個視窗可同屬一個 window classwindow class 並且使用同一個處理程式並且使用同一個處理程式

改變視窗大小

OS

message

你的應用程式

WndProc( ) function

Page 4: 視窗與訊息 (Window and Message)

MessageMessageLoader

載入應用程式

配置專屬Message Queue

執行 MessageLoop 讀取事件

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

message loop

Page 5: 視窗與訊息 (Window and Message)

Create window Create window 三個主要程序三個主要程序#include <windows.h>LRESULT CALLBACK WndProc( HWND,UINT,WPARAM,LPARAM);

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE …){

}

1. 註冊 Window Class RegisterClass(&wndclass)

1. 註冊 Window Class RegisterClass(&wndclass)

2. 建立視窗 hwnd=CreateWindow(…)

2. 建立視窗 hwnd=CreateWindow(…)

3. Message loop3. Message loop

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

4. 訊息處理函式LRESULT CALLBACK WndProc(HWND hwnd, …)

4. 訊息處理函式LRESULT CALLBACK WndProc(HWND hwnd, …)

Page 6: 視窗與訊息 (Window and Message)

1. 註冊 Window Class

WNDCLASS wndclass; wcx.cbSize = sizeof(wcx); // size of structure wcx.style = CS_HREDRAW | CS_VREDRAW; // redraw if size changes wcx.lpfnWndProc = MainWndProc; // points to window procedure wcx.cbClsExtra = 0; // no extra class memory wcx.cbWndExtra = 0; // no extra window memory wcx.hInstance = hinstance; // handle to instance wcx.hIcon = LoadIcon(NULL,IDI_APPLICATION); // predefined app. icon wcx.hCursor = LoadCursor(NULL,IDC_ARROW); // predefined arrow wcx.hbrBackground =(HBRUSH) GetStockObject(WHITE_BRUSH); wcx.lpszMenuName = NULL; // name of menu resource wcx.lpszClassName = "MainWClass";

WNDCLASS wndclass; wcx.cbSize = sizeof(wcx); // size of structure wcx.style = CS_HREDRAW | CS_VREDRAW; // redraw if size changes wcx.lpfnWndProc = MainWndProc; // points to window procedure wcx.cbClsExtra = 0; // no extra class memory wcx.cbWndExtra = 0; // no extra window memory wcx.hInstance = hinstance; // handle to instance wcx.hIcon = LoadIcon(NULL,IDI_APPLICATION); // predefined app. icon wcx.hCursor = LoadCursor(NULL,IDC_ARROW); // predefined arrow wcx.hbrBackground =(HBRUSH) GetStockObject(WHITE_BRUSH); wcx.lpszMenuName = NULL; // name of menu resource wcx.lpszClassName = "MainWClass";

RegisterClass(&wndclass)指定你的 windows class name

將你的 class name 註冊

如果寬度或高度改變 , 則重畫整個視窗

Page 7: 視窗與訊息 (Window and Message)

2.2. 建立視窗

hwnd = CreateWindow ("MainWClass", // window class name TEXT ("The Hello Program"), // window caption WS_OVERLAPPEDWINDOW, // window style CW_USEDEFAULT, // initial x position CW_USEDEFAULT, // initial y position CW_USEDEFAULT, // initial x size CW_USEDEFAULT, // initial y size NULL, // parent window handle NULL, // window menu handle hInstance, // program instance handle NULL) ; // creation parameters ShowWindow (hwnd, iCmdShow) ; UpdateWindow (hwnd) ;

hwnd = CreateWindow ("MainWClass", // window class name TEXT ("The Hello Program"), // window caption WS_OVERLAPPEDWINDOW, // window style CW_USEDEFAULT, // initial x position CW_USEDEFAULT, // initial y position CW_USEDEFAULT, // initial x size CW_USEDEFAULT, // initial y size NULL, // parent window handle NULL, // window menu handle hInstance, // program instance handle NULL) ; // creation parameters ShowWindow (hwnd, iCmdShow) ; UpdateWindow (hwnd) ;

指定你前面設定好的 windows class name指定你前面設定好的 windows class name

這個變數由 WinMain 參數得到

這個變數由 WinMain 參數得到

把視窗顯示出來把視窗顯示出來

*WS_XXX Window style 選項* CW_ XXX Create Window 選項

Page 8: 視窗與訊息 (Window and Message)

訊息處理函式 – WinProc( )LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){ HDC hdc ; PAINTSTRUCT ps ; RECT rect ; switch (message) { case WM_CREATE: PlaySound (TEXT ("hellowin.wav"), NULL, SND_FILENAME | SND_ASYNC) ; return 0 ; case WM_PAINT: hdc = BeginPaint (hwnd, &ps) ; GetClientRect (hwnd, &rect) ; DrawText (hdc, TEXT ("Hello, Windows 2000!"), -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER) ; EndPaint (hwnd, &ps) ; return 0 ; case WM_DESTROY: PostQuitMessage (0) ; return 0 ; } return DefWindowProc (hwnd, message, wParam, lParam) ; // 呼叫預設的 window procedure } // 做預設的處理 , 以保證每一個 message 都被處 // 理

當 window 剛被建立時 , 撥放音效檔當 window 剛被建立時 , 撥放音效檔

當 window 被要求重新繪製時 , 要做的工作當 window 被要求重新繪製時 , 要做的工作

當 window 被刪除時 , 要做的工作當 window 被刪除時 , 要做的工作

Page 9: 視窗與訊息 (Window and Message)

Uppercase IdentifiersUppercase Identifiers

CS_HREDRAW DT_VCENTER SND_FILENAME

CS_VREDRAW IDC_ARROW WM_CREATE

CW_USEDEFAULT IDI_APPLICATION WM_DESTROY

DT_CENTER MB_ICONERROR WM_PAINT

DT_SINGLELINE SND_ASYNC WS_OVERLAPPEDWINDOW

Prefix Constant

CS Class style option

CW Create window option

DT Draw text option

IDI ID number for an icon

IDC ID number for a cursor

MB Message box options

SND Sound option

WM Window message

WS Window style

WM_PAINT 屬於 Window message

Page 10: 視窗與訊息 (Window and Message)

New Data TypeNew Data Type

UINT UINT unsigned int unsigned int

PSTR PSTR char * char *

LRESULT LRESULT LONG LONG

16-bit Windows16-bit Windows 32-bit Windows32-bit Windows

WPARAMWPARAM WORDWORD UINT UINT

LPARAMLPARAM LONGLONG LONGLONG

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow);

LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;

_stdcall

__stdcall: fun(1,2,3,4)1. 最右邊的參數先推入堆疊2. 函式返回前 , 自行移除堆疊中的參數*Win32 API 使用 __stdcall

先 push 進堆疊先 push 進堆疊

節省程式碼的原因

Page 11: 視窗與訊息 (Window and Message)

Getting a Handle on HandlesGetting a Handle on Handles

Handle Handle 在視窗程式中使用的非常頻繁在視窗程式中使用的非常頻繁– 一個整數一個整數– 他代表一個物件他代表一個物件– Windows Windows 使用代號來操作物件使用代號來操作物件

Identifier Meaning

HINSTANCE Handle to an "instance"—the program itself

HWND Handle to a window

HDC Handle to a device context 我們已經看過的 handle如果你需要輸出資料到裝置你會需要 DC

Page 12: 視窗與訊息 (Window and Message)

Hungarian Notation (Hungarian Notation ( 匈牙利表示匈牙利表示法法 ))

紀念 紀念 Microsoft Microsoft 程式設計師 程式設計師 Charles SimonyiCharles Simonyi

變數名稱以一個或多個變數名稱以一個或多個小寫字母小寫字母開始開始– 這些字母表示資料型態這些字母表示資料型態

szszCmdLine CmdLine 以以 0 0 結尾的字串結尾的字串hhInstance Instance 與 與 hhPrevInstance PrevInstance h h 表示 表示 HandleHandleiiCmdShow CmdShow i i 表示 表示 intint

structure structure 變數變數– 以 以 structure name structure name 為小寫當 為小寫當 prefix prefix 或 變數的名稱或 變數的名稱

msg msg MSG structure MSG structurecndclass cndclass WNDCLASSES structure WNDCLASSES structureps ps PAINTSTRUCT structure PAINTSTRUCT structurerect rect RECT structure RECT structure

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnvsgen/html/hunganotat.asp匈牙利表示法進一步參考資料匈牙利表示法進一步參考資料 ::

Page 13: 視窗與訊息 (Window and Message)

附錄附錄 : : 完整的程式碼 完整的程式碼 #include <windows.h>// 視窗訊息處理函式的 prototypeLRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ; // Windows 程式第一個進入點 WinMain(...) int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow){ static TCHAR szAppName[] = TEXT ("HelloWin") ; HWND hwnd ; MSG msg ; // ===============Step 1: 建立並且註冊 Window Class ============= WNDCLASS wndclass ; wndclass.style = CS_HREDRAW | CS_VREDRAW ; wndclass.lpfnWndProc = WndProc ; // << -- 設定視窗訊息處理函式位置 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 = szAppName ; // << -- 指定目前的 class name

#include <windows.h>// 視窗訊息處理函式的 prototypeLRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ; // Windows 程式第一個進入點 WinMain(...) int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow){ static TCHAR szAppName[] = TEXT ("HelloWin") ; HWND hwnd ; MSG msg ; // ===============Step 1: 建立並且註冊 Window Class ============= WNDCLASS wndclass ; wndclass.style = CS_HREDRAW | CS_VREDRAW ; wndclass.lpfnWndProc = WndProc ; // << -- 設定視窗訊息處理函式位置 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 = szAppName ; // << -- 指定目前的 class name

Page 14: 視窗與訊息 (Window and Message)

// ============== Step 2: 建立視窗並且傳回 window handle ========== hwnd = CreateWindow (szAppName, // 指定 window class name TEXT ("The Hello Program"), // window caption WS_OVERLAPPEDWINDOW, // window style CW_USEDEFAULT, // initial x position CW_USEDEFAULT, // initial y position CW_USEDEFAULT, // initial x size CW_USEDEFAULT, // initial y size NULL, // parent window handle NULL, // window menu handle hInstance, // program instance handle NULL) ; // creation parameters // =============== Step 3: 把視窗顯示出來 ======================== ShowWindow (hwnd, iCmdShow) ; UpdateWindow (hwnd) ;

// =============== Step 4: Message - Loop 的部分 =================== while (GetMessage (&msg, NULL, 0, 0)) { TranslateMessage (&msg) ; DispatchMessage (&msg) ; } return msg.wParam ;}

// ============== Step 2: 建立視窗並且傳回 window handle ========== hwnd = CreateWindow (szAppName, // 指定 window class name TEXT ("The Hello Program"), // window caption WS_OVERLAPPEDWINDOW, // window style CW_USEDEFAULT, // initial x position CW_USEDEFAULT, // initial y position CW_USEDEFAULT, // initial x size CW_USEDEFAULT, // initial y size NULL, // parent window handle NULL, // window menu handle hInstance, // program instance handle NULL) ; // creation parameters // =============== Step 3: 把視窗顯示出來 ======================== ShowWindow (hwnd, iCmdShow) ; UpdateWindow (hwnd) ;

// =============== Step 4: Message - Loop 的部分 =================== while (GetMessage (&msg, NULL, 0, 0)) { TranslateMessage (&msg) ; DispatchMessage (&msg) ; } return msg.wParam ;}

Page 15: 視窗與訊息 (Window and Message)

// 視窗訊息處理函式LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){ HDC hdc ; PAINTSTRUCT ps ; RECT rect ; switch (message) { case WM_CREATE: // << -- 當視窗被建立時 , 事件處理程式碼 PlaySound (TEXT ("hellowin.wav"), NULL, SND_FILENAME | SND_ASYNC) ; return 0 ; case WM_PAINT: // << -- 當視窗被要求重新繪製時 , 事件處理程式碼 hdc = BeginPaint (hwnd, &ps) ; GetClientRect (hwnd, &rect) ; DrawText (hdc, TEXT ("Hello, Windows!"), -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER) ; EndPaint (hwnd, &ps) ; return 0 ; case WM_DESTROY: PostQuitMessage (0) ; return 0 ; } return DefWindowProc (hwnd, message, wParam, lParam) ;}

// 視窗訊息處理函式LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){ HDC hdc ; PAINTSTRUCT ps ; RECT rect ; switch (message) { case WM_CREATE: // << -- 當視窗被建立時 , 事件處理程式碼 PlaySound (TEXT ("hellowin.wav"), NULL, SND_FILENAME | SND_ASYNC) ; return 0 ; case WM_PAINT: // << -- 當視窗被要求重新繪製時 , 事件處理程式碼 hdc = BeginPaint (hwnd, &ps) ; GetClientRect (hwnd, &rect) ; DrawText (hdc, TEXT ("Hello, Windows!"), -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER) ; EndPaint (hwnd, &ps) ; return 0 ; case WM_DESTROY: PostQuitMessage (0) ; return 0 ; } return DefWindowProc (hwnd, message, wParam, lParam) ;}

End of HelloWin.c

Page 16: 視窗與訊息 (Window and Message)

在你專案目錄中的重要檔案在你專案目錄中的重要檔案

FileFile DescriptionDescription

Debug Debug 目錄目錄 執行檔與暫存檔HelloWinHelloWin.vcproj.vcproj Visual C++ .Net 專案檔HelloWin.slnHelloWin.sln 包含 .vcproj 進入點的 solution file

HelloWin.c (HelloWin.c ( 或 或 cpp)cpp) Source file

.rc.rc Resource Script file

HellWin.ncbHellWin.ncb InteliSense Database file 可刪除可刪除

可刪除可刪除

Page 17: 視窗與訊息 (Window and Message)

編譯你的程式編譯你的程式找不到 PlaySoundA

你必須 import library winmm.lib

Project HelloWin Properties …

Step 1: Input

Step 2: Addition Dependence winmm.lib

winmm.lib

Page 18: 視窗與訊息 (Window and Message)

試著建立一個 試著建立一個 simple windows applicationsimple windows application

Page 19: 視窗與訊息 (Window and Message)

附錄附錄 : : (MFC (MFC 相關相關 )) 如何處理 如何處理 Button Button 的訊的訊息息

你可以藉由 Control Events tab 設定在主視窗中的 childwindow( 按鈕 )的 event 處理 !

但是 , 若我想要接收更多的事件時 , 要如何做 ?( 因為 Control Events tab 中沒有相關的設定 )

Page 20: 視窗與訊息 (Window and Message)

所有視窗的 所有視窗的 messagemessage

ms-help://MS.MSDNQTR.2004JAN.1033/vclib/html/_mfc_wm__message_handlers.3a_.l_.2d_.m.htm

L-M 的項目

你要 override 的部分你要 override 的部分

滑鼠按左鍵滑鼠按左鍵

滑鼠移動滑鼠移動

Page 21: 視窗與訊息 (Window and Message)

處理滑鼠按左鍵處理滑鼠按左鍵你必須要繼承 你必須要繼承 CButton, CButton, 並根據上一頁說並根據上一頁說明明 ,, 需要 需要 override override

afx_msg void OnLButtonDown( UINT nFlags, CPoint point );

你新按鈕類別的長相應該是長這樣你新按鈕類別的長相應該是長這樣

testDlg.h

Page 22: 視窗與訊息 (Window and Message)

建立新按鈕建立新按鈕新增一個按鈕新增一個按鈕 , , 在 在 Dialog Dialog 中中

testDlg.h

testDlg.cpp

結果結果

自訂處理按鈕事件