您的位置:首页 > 编程语言 > C语言/C++

windows C语言编程——模态对话框

2017-01-19 16:03 190 查看
模态对话框,就是当程序显示此对话框时,用户不能在对话框和该程序的其他窗口之间进行切换。来看一个例子:

/*------------------------------------------
ABOUT2.C -- About Box Demo Program No. 2
(c) Charles Petzold, 1998
------------------------------------------*/

#include <windows.h>
#include "resource.h"

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

int iCurrentColor  = IDC_BLACK,
iCurrentFigure = IDC_RECT ;

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
static TCHAR szAppName[] = TEXT ("About2") ;
MSG          msg ;
HWND         hwnd ;
WNDCLASS     wndclass ;

wndclass.style         = CS_HREDRAW | CS_VREDRAW ;
wndclass.lpfnWndProc   = WndProc ;
wndclass.cbClsExtra    = 0 ;
wndclass.cbWndExtra    = 0 ;
wndclass.hInstance     = hInstance ;
wndclass.hIcon         = LoadIcon (hInstance, szAppName) ;
wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
wndclass.lpszMenuName  = szAppName ;
wndclass.lpszClassName = szAppName ;

if (!RegisterClass (&wndclass))
{
MessageBox (NULL, TEXT ("This program requires Windows NT!"),
szAppName, MB_ICONERROR) ;
return 0 ;
}

hwnd = CreateWindow (szAppName, TEXT ("About Box Demo Program"),
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL) ;

ShowWindow (hwnd, iCmdShow) ;
UpdateWindow (hwnd) ;

while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
return msg.wParam ;
}

void PaintWindow (HWND hwnd, int iColor, int iFigure)
{
static COLORREF crColor[8] = { RGB (  0,   0, 0), RGB (  0,   0, 255),
RGB (  0, 255, 0), RGB (  0, 255, 255),
RGB (0xff,   0, 0), RGB (255,   0, 255),
RGB (255, 255, 0), RGB (255, 255, 255) } ;

HBRUSH          hBrush ;
HDC             hdc ;
RECT            rect ;

hdc = GetDC (hwnd) ;
GetClientRect (hwnd, &rect) ;
hBrush = CreateSolidBrush (crColor[iColor - IDC_BLACK]) ;
hBrush = (HBRUSH) SelectObject (hdc, hBrush) ;

if (iFigure == IDC_RECT)
Rectangle (hdc, rect.left, rect.top, rect.right, rect.bottom) ;
else
Ellipse   (hdc, rect.left, rect.top, rect.right, rect.bottom) ;

DeleteObject (SelectObject (hdc, hBrush)) ;
ReleaseDC (hwnd, hdc) ;
}

void PaintTheBlock (HWND hCtrl, int iColor, int iFigure)
{
InvalidateRect (hCtrl, NULL, TRUE) ;
UpdateWindow (hCtrl) ;
PaintWindow (hCtrl, iColor, iFigure) ;
}

LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static HINSTANCE hInstance ;
PAINTSTRUCT      ps ;

switch (message)
{
case WM_CREATE:
hInstance = ((LPCREATESTRUCT) lParam)->hInstance ;
return 0 ;

case WM_COMMAND:
switch (LOWORD (wParam))
{
case IDM_APP_ABOUT:
if (DialogBox (hInstance, TEXT ("AboutBox"), hwnd, AboutDlgProc))
InvalidateRect (hwnd, NULL, TRUE) ;
return 0 ;
}
break ;

case WM_PAINT:
BeginPaint (hwnd, &ps) ;
EndPaint (hwnd, &ps) ;

PaintWindow (hwnd, iCurrentColor, iCurrentFigure) ;
return 0 ;

case WM_DESTROY:
PostQuitMessage (0) ;
return 0 ;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}

BOOL CALLBACK AboutDlgProc (HWND hDlg, UINT message,
WPARAM wParam, LPARAM lParam)
{
static HWND hCtrlBlock ;
static int  iColor, iFigure ;

switch (message)
{
case WM_INITDIALOG:
iColor  = iCurrentColor ;
iFigure = iCurrentFigure ;

CheckRadioButton (hDlg, IDC_BLACK, IDC_WHITE,   iColor) ;
CheckRadioButton (hDlg, IDC_RECT,  IDC_ELLIPSE, iFigure) ;

hCtrlBlock = GetDlgItem (hDlg, IDC_PAINT) ;

SetFocus (GetDlgItem (hDlg, iColor)) ;
return FALSE ;

case WM_COMMAND:
switch (LOWORD (wParam))
{
case IDOK:
iCurrentColor  = iColor ;
iCurrentFigure = iFigure ;
EndDialog (hDlg, TRUE) ;
return TRUE ;

case IDCANCEL:
EndDialog (hDlg, FALSE) ;
return TRUE ;

case IDC_BLACK:
case IDC_RED:
case IDC_GREEN:
case IDC_YELLOW:
case IDC_BLUE:
case IDC_MAGENTA:
case IDC_CYAN:
case IDC_WHITE:
iColor = LOWORD (wParam) ;
CheckRadioButton (hDlg, IDC_BLACK, IDC_WHITE, LOWORD (wParam)) ;
PaintTheBlock (hCtrlBlock, iColor, iFigure) ;
return TRUE ;

case IDC_RECT:
case IDC_ELLIPSE:
iFigure = LOWORD (wParam) ;
CheckRadioButton (hDlg, IDC_RECT, IDC_ELLIPSE, LOWORD (wParam)) ;
PaintTheBlock (hCtrlBlock, iColor, iFigure) ;
return TRUE ;
}
break ;

case WM_PAINT:
PaintTheBlock (hCtrlBlock, iColor, iFigure) ;
break ;
}
return FALSE ;
}

涉及到的头文件,也就是resource.h的主要代码:

#define IDC_BLACK                       1000
#define IDC_BLUE                        1001
#define IDC_GREEN                       1002
#define IDC_CYAN                        1003
#define IDC_RED                         1004
#define IDC_MAGENTA                     1005
#define IDC_YELLOW                      1006
#define IDC_WHITE                       1007
#define IDC_RECT                        1008
#define IDC_ELLIPSE                     1009
#define IDC_PAINT                       1010
#define IDM_APP_ABOUT                   40001

资源文件的主要代码:

ABOUTBOX DIALOG DISCARDABLE  32, 32, 200, 234
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION
FONT 8, "MS Sans Serif"
BEGIN
ICON            "ABOUT2",IDC_STATIC,7,7,20,20
CTEXT           "About2",IDC_STATIC,57,12,86,8
CTEXT           "About Box Demo Program",IDC_STATIC,7,40,186,8
LTEXT           "",IDC_PAINT,114,67,72,72
GROUPBOX        "&Color",IDC_STATIC,7,60,84,143
RADIOBUTTON     "&Black",IDC_BLACK,16,76,64,8,WS_GROUP | WS_TABSTOP
RADIOBUTTON     "B&lue",IDC_BLUE,16,92,64,8
RADIOBUTTON     "&Green",IDC_GREEN,16,108,64,8
RADIOBUTTON     "Cya&n",IDC_CYAN,16,124,64,8
RADIOBUTTON     "&Red",IDC_RED,16,140,64,8
RADIOBUTTON     "&Magenta",IDC_MAGENTA,16,156,64,8
RADIOBUTTON     "&Yellow",IDC_YELLOW,16,172,64,8
RADIOBUTTON     "&White",IDC_WHITE,16,188,64,8
GROUPBOX        "&Figure",IDC_STATIC,109,156,84,46,WS_GROUP
RADIOBUTTON     "Rec&tangle",IDC_RECT,116,172,65,8,WS_GROUP | WS_TABSTOP
RADIOBUTTON     "&Ellipse",IDC_ELLIPSE,116,188,64,8
DEFPUSHBUTTON   "OK",IDOK,35,212,50,14,WS_GROUP
PUSHBUTTON      "Cancel",IDCANCEL,113,212,50,14,WS_GROUP
END

ABOUT2                  ICON    DISCARDABLE     "About2.ico"

ABOUT2 MENU DISCARDABLE
BEGIN
POPUP "&Help"
BEGIN
MENUITEM "&About",                      IDM_APP_ABOUT
END
END

#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO DISCARDABLE
BEGIN
"ABOUTBOX", DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 193
TOPMARGIN, 7
BOTTOMMARGIN, 227
END
END
#endif    // APSTUDIO_INVOKED

运行效果如下:



程序的作用是,通过弹出的对话框选择颜色,然后再选择椭圆还是矩形,单击确定时将选择的东西在主窗口中显示出相应的效果。这个程序看起来并不复杂,但涉及到的知识还是很多的,所以值得细说一下。

1,关于WS_GROUP和WS_TABSTOP。

2,坐标值的大小。

3,对话框过程及激活对话框。

4,对话框的外边框。

5,关于RGB的创建。

6,关于WS_SYSMENU。

7,CONTROL语句与CreateWindow的关系。

8,关于设备环境句柄(HDC)及PAINTSTRUCT结构。获取HDC有两种方式:

PAINTSTRUCT      ps ;
....
hdc = BeginPaint (hwnd, &ps) ;
....
EndPaint (hwnd, &ps) ;

hdc = GetDC (hwnd) ;
....
ReleaseDC (hwnd, hdc) ;

BeginPaint函数的作用是擦去无效区域的背景以便绘图,同时还会填充PAINTSTRUST结构的各个字段,并返回HDC,它与EndPaint必须成对出现。而上面的代码中,如果BeginPaint与EndPaint之间没有任何绘制图形的代码,作用是将无效区域有效化。

GetDC与ReleaseDC有点类似,也必须成对出现,将GetDC返回的设备环境句柄中的裁剪矩形是整个客户区,而BeginPaint可以是部分区域。需要绘制的区域是存放在PAINTSTRUST结构中,该结构定义如下:

typedef struct tagPAINTSTRUCT {
HDC         hdc;
BOOL        fErase;
RECT        rcPaint;
BOOL        fRestore;
BOOL        fIncUpdate;
BYTE        rgbReserved[32];
} PAINTSTRUCT, *PPAINTSTRUCT, *NPPAINTSTRUCT, *LPPAINTSTRUCT;

第三个字段RECT rcPaint,即存放需要绘制图形的矩形区域,这里面的值可以通过下列函数传过来。

BOOL InvalidateRect(
HWND hWnd,	// handle of window with changed update region
CONST RECT *lpRect,	// address of rectangle coordinates
BOOL bErase	// erase-background flag
);

这个函数的第二个字段便是需绘制矩形的值。重要绘制整个客户区可以采用以下方式:

InvalidateRect(hwnd,NULL,TRUE)

9,绘制填充区域背景。

10,关于DialogBoxParam。

11,关于在主窗口绘制不同的图形。

以上几个方面,对于理解这个程序来说很重要,也涉及到很多Windows API编程的基础知识,值得反复研究。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: