1. 程式人生 > >win32開發(訊息機制)

win32開發(訊息機制)

【 宣告:版權所有,歡迎轉載,請勿用於商業用途。 聯絡信箱:feixiaoxing @163.com】

    win32真正的本質其實就是訊息機制。大家如果除錯win32程式,就會發現win32的應用其實是一個單執行緒程式碼,這至少說明windows提供的demo code是單執行緒應用。既然是單執行緒應用,那麼基本上說明這個應用是一個dead loop程式碼。作為迴圈程式碼來說,它不可能一直在執行,那麼勢必會阻塞在某一個地方,或者在某一個函式裡面,否則cpu佔有率會一直保持在100%了。

    想到這,大家或許就清楚了,win32其實就是一個訊息處理的應用。所有的處理都是通過訊息回撥的形式進行的。換句話說就是,你只要處理好系統發給你的訊息就可以了,剩下的就是你把對應的回撥函式準備好就ok了,大體就是這個意思。

// tt.cpp : Defines the entry point for the application.
//

#include "stdafx.h"
#include "resource.h"

#define MAX_LOADSTRING 100

// Global Variables:
HINSTANCE hInst;								// current instance
TCHAR szTitle[MAX_LOADSTRING];								// The title bar text
TCHAR szWindowClass[MAX_LOADSTRING];								// The title bar text

// Foward declarations of functions included in this code module:
ATOM				MyRegisterClass(HINSTANCE hInstance);
BOOL				InitInstance(HINSTANCE, int);
LRESULT CALLBACK	WndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK	About(HWND, UINT, WPARAM, LPARAM);

int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{
 	// TODO: Place code here.
	MSG msg;
	HACCEL hAccelTable;

	// Initialize global strings
	LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
	LoadString(hInstance, IDC_TT, szWindowClass, MAX_LOADSTRING);
	MyRegisterClass(hInstance);

	// Perform application initialization:
	if (!InitInstance (hInstance, nCmdShow)) 
	{
		return FALSE;
	}

	hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_TT);

	// Main message loop:
	while (GetMessage(&msg, NULL, 0, 0)) 
	{
		if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) 
		{
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
	}

	return msg.wParam;
}



//
//  FUNCTION: MyRegisterClass()
//
//  PURPOSE: Registers the window class.
//
//  COMMENTS:
//
//    This function and its usage is only necessary if you want this code
//    to be compatible with Win32 systems prior to the 'RegisterClassEx'
//    function that was added to Windows 95. It is important to call this function
//    so that the application will get 'well formed' small icons associated
//    with it.
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
	WNDCLASSEX wcex;

	wcex.cbSize = sizeof(WNDCLASSEX); 

	wcex.style			= CS_HREDRAW | CS_VREDRAW;
	wcex.lpfnWndProc	= (WNDPROC)WndProc;
	wcex.cbClsExtra		= 0;
	wcex.cbWndExtra		= 0;
	wcex.hInstance		= hInstance;
	wcex.hIcon			= LoadIcon(hInstance, (LPCTSTR)IDI_TT);
	wcex.hCursor		= LoadCursor(NULL, IDC_ARROW);
	wcex.hbrBackground	= (HBRUSH)(COLOR_WINDOW+1);
	wcex.lpszMenuName	= (LPCSTR)IDC_TT;
	wcex.lpszClassName	= szWindowClass;
	wcex.hIconSm		= LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL);

	return RegisterClassEx(&wcex);
}

//
//   FUNCTION: InitInstance(HANDLE, int)
//
//   PURPOSE: Saves instance handle and creates main window
//
//   COMMENTS:
//
//        In this function, we save the instance handle in a global variable and
//        create and display the main program window.
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
   HWND hWnd;

   hInst = hInstance; // Store instance handle in our global variable

   hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
      CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);

   if (!hWnd)
   {
      return FALSE;
   }

   ShowWindow(hWnd, nCmdShow);
   UpdateWindow(hWnd);

   return TRUE;
}

//
//  FUNCTION: WndProc(HWND, unsigned, WORD, LONG)
//
//  PURPOSE:  Processes messages for the main window.
//
//  WM_COMMAND	- process the application menu
//  WM_PAINT	- Paint the main window
//  WM_DESTROY	- post a quit message and return
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	int wmId, wmEvent;
	PAINTSTRUCT ps;
	HDC hdc;
	TCHAR szHello[MAX_LOADSTRING];
	LoadString(hInst, IDS_HELLO, szHello, MAX_LOADSTRING);

	switch (message) 
	{
		case WM_COMMAND:
			wmId    = LOWORD(wParam); 
			wmEvent = HIWORD(wParam); 
			// Parse the menu selections:
			switch (wmId)
			{
				case IDM_ABOUT:
				   DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)About);
				   break;
				case IDM_EXIT:
				   DestroyWindow(hWnd);
				   break;
				default:
				   return DefWindowProc(hWnd, message, wParam, lParam);
			}
			break;
		case WM_PAINT:
			hdc = BeginPaint(hWnd, &ps);
			// TODO: Add any drawing code here...
			RECT rt;
			GetClientRect(hWnd, &rt);
			DrawText(hdc, szHello, strlen(szHello), &rt, DT_CENTER);
			EndPaint(hWnd, &ps);
			break;
		case WM_DESTROY:
			PostQuitMessage(0);
			break;
		default:
			return DefWindowProc(hWnd, message, wParam, lParam);
   }
   return 0;
}

// Mesage handler for about box.
LRESULT CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
	switch (message)
	{
		case WM_INITDIALOG:
				return TRUE;

		case WM_COMMAND:
			if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) 
			{
				EndDialog(hDlg, LOWORD(wParam));
				return TRUE;
			}
			break;
	}
    return FALSE;
}
    這個程式碼大體出現過很多次。其實最重要的地方就三個,一個是MyRegisterClass函式,它最重要的意義就是定義了WndProc這個回撥入口,它告訴os所有的訊息響應,你直接call這個函式就可以了。當然,如果是mdi程式,還是要定義多個WNDCLASSEX的。第二個函式就是InitInstance,它的意義就是建立了一個控制代碼為hWnd的視窗,一個app可以建立很多個視窗,但是所有的視窗訊息入口都是WndProc。這裡的多視窗指的是多視窗控制元件。注意這裡szWindowClass引數的意義。第三個函式毫無疑問,就是WndProc。它是真正處理訊息的地方,這些訊息有些只會出現一次,比如WM_DESTROY。有些會不停出現,比如WM_PAINT、WM_SIZE這些。至於About函式,其實它就是DialogBox的回撥入口,本質上和WndProc是一樣的。如果大家有興趣,會發現About函式處理的時候,回溯堆疊裡面就有WndProc,這說明他們其實都是在處理訊息而已。

    至於訊息是什麼時候獲取的,大家看這個迴圈就可以了,

	// Main message loop:
	while (GetMessage(&msg, NULL, 0, 0)) 
	{
		if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) 
		{
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
	}

    有訊息的時候就處理訊息,如果系統沒有給app傳送訊息,那麼GetMessage會被block住。如果換成另外一個函式PeekMessage,那基本上就是deadloop了,所以兩個函式其實是不一樣的。windows的訊息大體分成三種,一種是WM_COMMAND,這種處理選單、工具欄等訊息。一種是WM_NOTIFY,它處理元件送過來的資訊,比如list控制元件、tree控制元件等等。第三種就是系統訊息,這包括WM_PAINT,WM_CREATE,WM_SIZE,WM_DESTROY等等。學到什麼訊息,就用什麼訊息就可以了。

相關推薦

win32開發訊息機制

【 宣告:版權所有,歡迎轉載,請勿用於商業用途。 聯絡信箱:feixiaoxing @163.com】    win32真正的本質其實就是訊息機制。大家如果除錯win32程式,就會發現win32的應用其實是一個單執行緒程式碼,這至少說明windows提供的demo code是

Runtime那些事兒訊息機制

一、關於runtime 之前在專案中有遇到過用runtime解決改變全域性字型的問題,所以再一次感受到了runtime黑魔法的強大,趁現在有機會分享一下對runtime的一些理解。在物件呼叫方法是Objective-C中經常使用的功能,也就是訊息的傳遞,而Obj

WIN32學習——Windows訊息機制

1、Win32視窗程式採用的是事件驅動方式執行,也就是訊息機制,當系統通知視窗工作時,就是採用訊息的方式派發給視窗,通過呼叫視窗處理函式進行對訊息對處理。 2、訊息MessageBox結構體: int MessageBox( HWND hWnd, //父視窗

跟我一起玩Win32開發2:完整的開發流程

上一篇中我給各位說了一般人認為C++中較為難的東西——指標。其實對於C++,難點當然不侷限在指標這玩意兒上,還有一些有趣的概念,如模板類、虛基類、純虛擬函式等,這些都是概念性的東西,幾乎每一本C++書上都會介紹,而平時我們除了會接觸到純虛擬函式外,其他的不多用。純虛擬函式,

跟我一起玩Win32開發21:複製&貼上&剪貼簿操作

我要提醒一下大家,看了我的博文學到的知識,千萬不要用於實際開發,不然你會被你的上司罵:“媽的,這些東西哪來的,從來沒有人這樣做過。”不信你試試,腦細胞被凍結的經理或者技術總監們肯定會這樣說的。 如果是一些有X年工作經驗(X永遠不可能大於100)的程式設計師肯定會說:“你怎麼

微信公眾平臺開發十二 傳送客服訊息

原文:https://www.cnblogs.com/mchina/p/3711217.html   微信公眾平臺開發(十二) 傳送客服訊息 一、簡介 當用戶主動發訊息給公眾號的時候(包括髮送資訊、點選自定義選單、訂閱事件、掃描二維碼事件、支付成功事件、使用者維權),微信將

win32開發檔案、字型和色彩

【 宣告:版權所有,歡迎轉載,請勿用於商業用途。 聯絡信箱:feixiaoxing @163.com】    在作業系統上,檔案選擇、色彩選擇、和字型選擇這些功能一般都是作業系統提供的。記得以前在寫mfc的時候,由於基本功能都是mfc封裝好的,每次呼叫的時候都覺得非常得神奇,

跟我一起玩Win32開發23:漸變顏色填充

GradientFill函式可以對特定的矩形區域或者三角形區域進行漸變顏色的填充。我們先來看看GradientFill函式到底長得什麼樣子,帥不帥。 BOOL GradientFill( _In_ HDC hdc, _In_ PTRIVERTEX pVertex

Android訊息推送廣播機制+通知

Android廣播機制使用了觀察著模式; (1) 通知 1) 獲取狀態通知欄管理 NotificationManager 是一個系統Service,所以必須通過getSystemService(NO

基於TypeScript的FineUIMvc組件式開發開頭篇

clas toa 教程 cda 解決 處理 如何 show 文章 了解FineUIMvc的都知道,FineUIMvc中采用了大量的IFrame框架,對於IFrame的優缺點網上也有很多的討論,這裏我要說它的一個優點“有助於隔離代碼邏輯”,這也是FineUIMvc官網對它的描

php短信接口開發http協議

php短信接口 http協議短信接口 php短信接口開發 本文由動力思維樂信原創文章,技術楊工提供,歡迎交流合作,動力思維樂信短信接口官網:http://www.lx598.com/ 。 一、接口說明 1、提交方式與編碼 ht

python開發第二篇:初始python

登陸 文件 windows == del pwd keyword 入門 用c語言實現 erPython的種類: Cpython python的官方版本,使用C語言實現,使用最為廣泛,Cpython實現會將源文件()(py文件)轉換成字節碼文件(pyc文件)然後運行再p

CoreThink開發十一首頁控制器判斷移動設備還是PC並做相應處理

iss htm meizu http nec window sam assign clas 在home模塊Index控制器添加判斷代碼 application\Home\Controller\IndexController.class.php <?php // +

CoreThink開發十二更改默認出錯異常頁防止暴露敏感數據

highlight true pos pub light brush 關閉 sql exception 默認的異常頁會打印文件位置,而且是絕對路徑,會打印SQL語句,真實上線一定不要用這個默認的,而且關閉trace關閉調試模式也不行。 針對CoreThink1.2 Th

微信公眾號開發準備工作

code image 賬號 開發項目 pre 位置 基本 地理 不同 微信公眾號的開發,前期的服務器搭建,與微信服務器的接入等這些參考的都是souvc的個人博客,在這邊我只是記錄下自己開發項目的實際流程,如需具體了解,可到以下博客 一、服務器的搭建 本著勤儉節約的原則,

QT開發十七——QWT簡介

Qt QWTQT開發——QWT簡介 一、QWT簡介 QWT,即Qt Widgets for Technical Applications,是一個基於LGPL版權協議的開源項目, 可生成各種統計圖,是為具有技術專業背景的程序提供GUI組件和一組實用類,其目標是以基於2D方式的窗體部件來顯示數據, 數據源以數值,

基於hi-nginx的web開發python篇——cookie和會話管理

class status domain 登陸 edi 模板引擎 log 怎麽辦 cache hi-nginx通過redis管理會話。 要開啟管理,需要做三件事。 第一件開啟userid: userid on;

基於Skyline的web開發6.x

返回 lin 加載 code 場景 ner explorer 對象 設置 多窗口對比 一個頁面加載多個TerraExplorer3DWindow和SGWorld等只有第一個能用(即使用iframe也是一樣) 所以我決定打開兩個新頁面實現多窗口對比,然後我在《主頁面》使用wi

名師帶你學微信開發Java版

IT 視頻 ava 14. ade BE src pict idt ======================================================= 長期更新IT編程視頻教程,資料收集整理不易,需要一點費用 有意者加QQ:277

微信公眾號開發科普篇

名詞解釋 接口調用 sdk acc android平臺 調用 解釋 小程序 內容 公眾號分類 一、訂閱號 具有信息發布與傳播的能力,適合個人及媒體註冊二、服務號 具有用戶管理與提供業務服務的能力,適合企業及組織註冊三、企業號 具有實現企業內部溝通與內部協同