1. 程式人生 > >【win32】標記選單與對話方塊背景色

【win32】標記選單與對話方塊背景色

主要是想如下的一個程式,設定了一個標記選單,在選定不同選單的時候,客戶區的顏色會改變,以此說明win32對話方塊客戶區的背景顏色設定與標記選單使用。

比起MFC裡面的背景顏色改變,WIN32的要複雜得多,而選單的修改更是需要廢一番功夫,但是通過這個程式揭示了窗體程式的本質。


一、選單設定與修改

1、如下圖,開啟Resource.h,在#ifndef之前,已有的選單項之後,為自己新設定的選單選項,設定編號。


這裡,501-503分別對應紅色、綠色、藍色三個選單:

//自己新建的選單項
#define IDM_RED 501
#define IDM_GREEN 502
#define IDM_BLUE 503
2、之後,如下圖,對資原始檔XX.rc檢視程式碼。刪去用快捷鍵、對話方塊的程式碼。因為VS2010自帶的對話方塊,按ALT+/ ?會自動彈出對話方塊的。


對原有關於檔案、幫助的選單修改如下:

IDC_MENU_NOTE MENU
BEGIN
    POPUP "背景顏色改變(&C)"
    BEGIN
        MENUITEM "紅色(&R)",                IDM_RED
        MENUITEM "綠色(&G)",                IDM_GREEN
        MENUITEM "藍色(&B)",                IDM_BLUE
    END
END
3、接下來,就真的可以回到Menu_Note.cpp的訊息回撥函式LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)中程式設計了。修改如下:
int menu_id=0;
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	int wmId, wmEvent;
	PAINTSTRUCT ps;
	HDC hdc;

	// 獲取視窗上的整個選單欄的控制代碼  
	auto hmm = GetMenu(hWnd);  
	// 獲取第一個彈出選單,即[背景顏色改變]選單的控制代碼 
	auto hfmn = GetSubMenu(hmm, 0);  
	HBRUSH brush;//畫刷,用於改變客戶區的背景色
	RECT rect;//矩形,用於捕捉客戶區的大小
	switch (message)
	{
	case WM_COMMAND:
		wmId    = LOWORD(wParam);
		wmEvent = HIWORD(wParam);

		switch (wmId)//分析視窗的選擇
		{
		case IDM_RED:
			menu_id=IDM_RED;
			CheckMenuRadioItem(hfmn, IDM_RED, IDM_BLUE, IDM_RED, MF_BYCOMMAND);//令此選單單選
			//第一個引數是選單控制代碼、第二、三個引數是指明這個選單從哪個編號到哪個編號是單選的,第四個引數是選擇誰
			hdc=GetDC(hWnd);
			brush=CreateSolidBrush(RGB(255,0,0));//建立一個紅色畫刷
			GetClientRect(hWnd,&rect);//獲取客戶區這個大矩形到rect中
			FillRect(hdc,&rect,brush);//填充這個矩形
			break;  
		case IDM_GREEN:
			menu_id=IDM_GREEN;
			CheckMenuRadioItem(hfmn, IDM_RED, IDM_BLUE, IDM_GREEN, MF_BYCOMMAND); 			
			hdc=GetDC(hWnd);
			brush=CreateSolidBrush(RGB(0,255,0));
			GetClientRect(hWnd, &rect);
			FillRect(hdc,&rect, brush);
			break;
		case IDM_BLUE:
			menu_id=IDM_BLUE;
			CheckMenuRadioItem(hfmn, IDM_RED, IDM_BLUE, IDM_BLUE, MF_BYCOMMAND);	
			hdc=GetDC(hWnd);
			brush=CreateSolidBrush(RGB(0,0,255));
			GetClientRect(hWnd, &rect);
			FillRect(hdc,&rect, brush);
			break;
		}
		break;
	case WM_PAINT://如果使用者移動視窗、調整視窗的大小會發生重繪,那又要重新上色
		hdc = BeginPaint(hWnd, &ps);
		switch(menu_id){
		case 0:
			brush=CreateSolidBrush(RGB(255,255,255));		
			GetClientRect(hWnd, &rect);
			FillRect(hdc,&rect, brush);
			break;
		case IDM_RED:
			brush=CreateSolidBrush(RGB(255,0,0));	
			GetClientRect(hWnd, &rect);
			FillRect(hdc,&rect, brush);
			break;
		case IDM_GREEN:
			brush=CreateSolidBrush(RGB(0,255,0));		
			GetClientRect(hWnd, &rect);
			FillRect(hdc,&rect, brush);
			break;
		case IDM_BLUE:
			brush=CreateSolidBrush(RGB(0,0,255));	
			GetClientRect(hWnd, &rect);
			FillRect(hdc,&rect, brush);
			break;
		}
		EndPaint(hWnd, &ps);
		break;
	case WM_DESTROY:
		PostQuitMessage(0);
		break;
	default:
		return DefWindowProc(hWnd, message, wParam, lParam);
	}
	return 0;
}
其實,對於選單的核心在於呼叫CheckMenuRadioItem函式,第一個引數是要在其子項中設定的單選的選單的控制代碼,第二個引數和第三個引數指定合併為一個組的ID範圍,在這個範圍內的選單項被看人為同一組,這一組中,每一次只能有一項被checked,第四個引數就指定在這組項中哪一個被選中,最後一個引數決定是用ID來標識還用從0開始的索引。

至於設定對話方塊客戶區的背景色,這裡需要先設定畫刷的顏色,再獲取客戶區的矩形,再進行填充,填充的時候,注意獲取並初始化上下文HDC,HDC與HWND這個概念在《【win32】滑鼠響應事件》(點選開啟連結)已經提到過不在贅述。

這個程式同時需要設定一個全域性變數,記錄使用者當前選擇的是哪個標識選單,用於發生視窗重繪的時候,給客戶區的矩形重新上色。