程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> 關於C++ >> Win32開發入門(13) 握手對話框

Win32開發入門(13) 握手對話框

編輯:關於C++

一提到對話框,相信對它熟悉的人不在少數,更不用說碼農們了,你可能會問,對話框和窗口有什 麼區別嗎?本質上是沒有區別的,對話框也是一種窗口(前面也說過,控件也可視為子窗口)。

最簡單的對話框要數MessageBox彈出來的對話框了,是吧?這個函數我有信心,大家都會用的,畢 竟很簡單。

好的,廢話不多扯了,馬上開始本文第一件事,創建一個對話框。

對話框作為一種資源,它存放在資源文件中(.rc),如果項目中沒有rc文件,第一種方法是在“解 決方案資源管理器”中在“資源文件”節點右擊,從菜單中選擇“添加”-“新建項”來加入一個rc文 件。第二種方法,可以從VS的“視圖”菜單中打開“資源視圖”,在資源視圖中,在項目名節點上右擊 ,從菜單中找到“添加”-“資源”。

然後,選擇對話框,點新建按鈕。

在屬性窗口中為這個對話框名命一個ID,隨便你喜歡,我把它設為IDD_MYDLG。

OK,現在,我們就可以利用可視化設計器來玩了,看看,還不錯的,雖然沒有WinForm的設計器那麼 猛。

把默認兩個按鈕刪掉,我們從工具箱中拖放一些控件。記得為控件的ID命名,就像在WinForm裡面要 設置Name屬性一樣。

大概就這樣,拖一個Static Text和Button控件,隨後我們嘗試實現一個功能:點擊按鈕後,在靜態 文本框中顯示文本。這個編輯器怎麼用,就就不說了。

保存資源文件,下面我們開始寫代碼。

1、在主窗口的消息處理程序中響應WM_CREATE消息,用CreateDialog函數創建並顯示非模態對話框 。

LRESULT CALLBACK WinMainProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM LParam)
{
 HWND hdlg;
 switch (msg)
 {
 case WM_CREATE:
  hdlg = CreateDialog(hgapp,MAKEINTRESOURCE(IDD_MYDLG),hwnd,(DLGPROC)DlgProc);
  if(hdlg)
  {
   //顯示對話框
   ShowWindow(hdlg, SW_NORMAL);
  }
  return 0;
 case WM_DESTROY:
  PostQuitMessage(0);
  return 0;
 default:
  return DefWindowProc(hwnd,msg,wParam,LParam);
 }
 return 0;
}

CreateDialog的最後一個參數是一個CALLBACK,這個和我們的WindowProc是一鳥樣的,注意在定義 該函數時,一定要先在頭文件或源文件的前面聲明一下,不然到這裡會找不到,通常我們會把這些函數 都放到WinMain函數後面來寫,只是通常這樣,並不是說一定要這樣。

DlgProc如下:

// 處理對話框中的數據
INT_PTR CALLBACK DlgProc(HWND hdlg, UINT msg, WPARAM wParam, LPARAM lParam)
{
 
	return (INT_PTR)FALSE;
}


和WindowProc一樣,也有一個DefDlgProc,但是這裡最好不要調用,注意MSDN上關於這函數說明的最後 一段話。

The DefDlgProc function must not be called by a dialog box procedure; doing so results in recursive execution.

如果在DialogProc中調用DefDlgProc會導致死循環。其實,我們為窗口寫的消息循環也是死循環, GetMessage是不斷執行,除非接到WM_QUIT消息讓它返回假(0)就跳出循環,而對於對話框,我們並沒 有為它寫GetMessage,也不向它PostQuitMessage,它有可能會無法跳出循環。

現在,程序是可以運行的。

不過,無論你怎麼操作,對話框還是沒返應,因為現在我們還沒處理相關消息。

當用戶操作系統菜單或者點擊標題欄的 最大化, 最小化 或 關閉 按鈕,都會收到WM_SYSCOMMAND 消息,如果不響應WM_SYSCOMMAND,就會放到WM_COMMAND,但WM_COMMAND通常要處理控件的消息,故最 好用WM_SYSCOMMAND消息。

2、在對話框的DlgProc中響應WM_SYSCOMMAND。

	case WM_SYSCOMMAND:
		if(wParam == SC_CLOSE)
		{
			// 如果執行了關閉
			// 銷毀對話框,將收到WM_DESTROY消息
			DestroyWindow(hdlg);
		}
		return 0;

3、我們已經知道響應按鈕單擊是處理WM_COMMAND。要改變靜態文本中的文本,一可以用  Static_SetText宏,二可以用SetWindowText,三可以發送WM_SETTEXT消息。但是,無論采用哪 種方法,我們都得解決一個問題——怎麼獲取到靜態文本控件的句柄。所以,認識一下這個函數:

HWND WINAPI GetDlgItem(
  _In_opt_  HWND hDlg,
  _In_      int nIDDlgItem
);

你猜都猜到了,參數一是對話框的句柄,參數二是要返回句柄的控件的ID。好,我們試試。

	case WM_COMMAND:
		{
			if(LOWORD(wParam) == IDC_BTN)
			{
				nCount ++; //每點擊一次,就+1
				// 獲取控件句柄
				HWND hStatic = GetDlgItem(hdlg,IDC_DISP);
				// 設置控件文本
				WCHAR str[MAXCHAR];
				// 格式化字符串
				int n = wsprintf(str, L"你點擊了%d次按鈕。", 

nCount);
				//在最後一個字符後加上結止符
				str[n] = '\0';
				SetWindowText(hStatic, str);
			}
		}
		return 0;


現在來運行一下,每點擊一次按鈕,就會在靜態文本控件中顯示“你點擊了X次按鈕。

好,大功告成。

下面是完整的代碼清單。

#include <Windows.h>
#include "resource.h"
 
LRESULT CALLBACK WinMainProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM LParam);
INT_PTR CALLBACK DlgProc(HWND hdlg, UINT msg, WPARAM wParam, LPARAM lParam);
 
HINSTANCE hgapp; //當前應用程序句柄
int WINAPI WinMain(HINSTANCE hThisApp, HINSTANCE hPrevApp, LPSTR lpCmd, int nShow)
{
	LPCWSTR cn = L"My";
	WNDCLASS wc = {sizeof(WNDCLASS)};
	wc.hbrBackground = (HBRUSH)COLOR_WINDOW;
	wc.hInstance = hThisApp;
	wc.lpfnWndProc = WinMainProc;
	wc.lpszClassName = cn;
	wc.style = CS_HREDRAW | CS_VREDRAW;
	//注冊窗口類
	RegisterClass(&wc);
	//創建窗口
	HWND hwnd = CreateWindow(cn,L"主窗口",WS_OVERLAPPEDWINDOW,
		30,22,360,280,NULL,NULL,hThisApp,NULL);
	if(!hwnd)
		return 0;
	hgapp = hThisApp;
	//顯示窗口
	ShowWindow(hwnd,nShow);
	//更新窗口
	UpdateWindow(hwnd);
	//消息循環
	MSG msg;
	while (GetMessage(&msg,NULL,0,0))
	{
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}
	return 0;
}
 
LRESULT CALLBACK WinMainProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM LParam)
{
	HWND hdlg;
	switch (msg)
	{
	case WM_CREATE:
		hdlg = CreateDialog(hgapp,MAKEINTRESOURCE(IDD_MYDLG),hwnd,(DLGPROC)

DlgProc);
		if(hdlg)
		{
			//顯示對話框
			ShowWindow(hdlg, SW_NORMAL);
		}
		return 0;
	case WM_DESTROY:
		PostQuitMessage(0);
		return 0;
	default:
		return DefWindowProc(hwnd,msg,wParam,LParam);
	}
	return 0;
}
 
// 處理對話框中的數據
INT_PTR CALLBACK DlgProc(HWND hdlg, UINT msg, WPARAM wParam, LPARAM lParam)
{
	static int nCount = 0;//點擊按鈕的次數
	switch(msg)
	{
	case WM_SYSCOMMAND:
		if(wParam == SC_CLOSE)
		{
			// 如果執行了關閉
			// 銷毀對話框,將收到WM_DESTROY消息
			DestroyWindow(hdlg);
		}
		return 0;
	case WM_COMMAND:
		{
			if(LOWORD(wParam) == IDC_BTN)
			{
				nCount ++; //每點擊一次,就+1
				// 獲取控件句柄
				HWND hStatic = GetDlgItem(hdlg,IDC_DISP);
				// 設置控件文本
				WCHAR str[MAXCHAR];
				// 格式化字符串
				int n = wsprintf(str, L"你點擊了%d次按鈕。", nCount);
				//在最後一個字符後加上結止符
				str[n] = '\0';
				SetWindowText(hStatic, str);
			}
		}
		return 0;
	}
	return (INT_PTR)FALSE;
}
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved