一个界面进来首先要先进入初始化函数
例:
int ui_password_init(HWND hParent)
{
sg_PasswordDlg.controls = sg_ctrlsg_PasswordDlg;
sg_PasswordDlg.controlnr = TABLESIZE(sg_ctrlsg_PasswordDlg);
DialogBoxIndirectParam (&sg_PasswordDlg, hParent, uiPasswordProc, 0L);
return LL_INDOOR_SUCCESS;
}
可以看出,进入初始化函数之前需要给定参数HWND hParent
,这个为父窗口的句柄。
再去分析初始化函数内所需的变量,以上面代码为例,需要对话框结构体sg_PasswordDlg
、页面内所使用的控件sg_ctrlsg_PasswordDlg
、页面回调函数uiPasswordProc
,一个个分析。
在进入初始化函数之前首先要定义对话框结构体(例如例子中的sg_PasswordDlg
)。
接下来看一下这个sg_PasswordDlg
的结构
static DLGTEMPLATE sg_PasswordDlg=
{
WS_VISIBLE ,
WS_EX_NONE/* | WS_EX_AUTOSECONDARYDC*/,
0,0,272,480,
"",
0, 0,
0, NULL,
0
};
可以看出,这里定义了对话框的属性、起始坐标与宽高(一般照搬之后改一下宽高就行)。
再回到初始化函数,通过**sg_PasswordDlg.controls = sg_ctrlsg_PasswordDlg;**
对对话框使用的控件进行了指定;
接下来看一下这个sg_ctrlsg_PasswordDlg
这里面定义了什么。
static CTRLDATA sg_ctrlsg_PasswordDlg[] =
{
//密码
{
CTRL_STATIC,
WS_CHILD | WS_VISIBLE | SS_LEFT,
13,77,180,48,
ID_STATIC_PRIVATE_PASSWORD_CLICKED_PICTURE,
"",
0,
WS_EX_TRANSPARENT
},
//密码按钮
{
CTRL_BUTTON,
WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
13,60,220,48,
ID_PUSHBUTTON_PRIVATE_PASSWORD,
"",
0,
WS_EX_TRANSPARENT
},
/*余下控件省略*/
}
可以看出,这里面定义了一系列的控件,以第一个为例介绍
//密码
{
CTRL_STATIC,
WS_CHILD | WS_VISIBLE | SS_LEFT,
13,77,180,48,
ID_STATIC_PRIVATE_PASSWORD_CLICKED_PICTURE,
"",
0,
WS_EX_TRANSPARENT
},
简单来说这里定义了控件的属性、坐标与宽高,同时还指定了控件的ID:ID_STATIC_PRIVATE_PASSWORD_CLICKED_PICTURE
其余细节可参考官方的windows.h中定义的结构
/** Class name of the control */
const char* class_name;
/** Control style */
DWORD dwStyle;
/** Control position in dialog */
int x, y, w, h;
/** Control identifier
* \note The type changed from int to LINT since v3.2.
*/
LINT id;
/** Control caption */
const char* caption;
/** Additional data */
DWORD dwAddData;
/** Control extended style */
DWORD dwExStyle;
/** window element renderer name */
const char* werdr_name;
/** table of we_attrs */
const WINDOW_ELEMENT_ATTR* we_attrs;
这里的这个ID要着重说明一下,我们需要在该UI文件中定义一个枚举类型,专门用来收纳各个控件,同时也可满足对空间ID的定义,例如以下:
typedef enum {
ID_STATIC_COMMON_PASSWORD , /*通用密码 文字*/
ID_PUSHBUTTON_COMMON_PASSWORD , /*通用密码 选框*/
/*其余省略*/
}SYSSETING_PWD_DEFINE;
这样再回到最开始的初始化函数就可以发现控件的相关定义就已经完成了,就下来就剩一个控件回调函数uiPasswordProc
了。
static int uiPasswordProc (HWND hDlg, int nMessage, WPARAM wParam, LPARAM lParam)
{
int i;
g_bUIRun = TRUE;//防止UI界面死掉
switch (nMessage)
{
case MSG_CREATE:
{
sg_hPasswordDialog = hDlg;
break;
}
case MSG_PAINT:
{
HDC hdc = BeginPaint(hDlg);
RECT rect;
HWND hWnd;
//获取无效区域
GetUpdateRect(hDlg, &rect);
HDC Hdc = CreateCompatibleDC(hdc);
/*绘制文字*/
hWnd = GetDlgItem(hDlg, ID_STATIC_PRIVATE_PASSWORD_CLICKED_PICTURE);
if (hWnd)
{
SelectFont (hdc, default_font[MAIN_FONT_SIZE_17]);
GetWindowRect(hWnd, &rc);
DrawText(hdc, "一户一密码", -1, &rc, DT_LEFT| DT_VCENTER );
}
/*绘制图片*/
FillBoxWithBitmap(hdc,200,72,
bmp_setting[xxx].bmWidth, bmp_setting[xxx].bmHeight,
&bmp_setting[xxx]);
/*绘制纯色矩形*/
SetBrushColor(hdc, RGB2Pixel (HDC_SCREEN, 0xCE, 0xC9, 0xC9));
FillBox(hdc,0,59,272,1);
BitBlt(Hdc,rect.left,rect.top,RECTW(rect),RECTH(rect),hdc,rect.left,rect.top,0);
DeleteCompatibleDC(Hdc);
EndPaint(hDlg,hdc);
break;
}
case MSG_ERASEBKGND:
{
return 0;
}
case MSG_INITDIALOG:
{
/*省略*/
}
case MSG_SOFEKEY_SLEDIT_SAVE:
{
PostMessage(hDlg,MSG_COMMAND,ID_PUSHBUTTON_OK_PASSWORD,NULL);
break;
}
case MSG_COMMAND://按键触发
{
int nCmdId = LOWORD (wParam);
int nNc = HIWORD (wParam);
HWND hWnd = GetDlgItem(hDlg, nCmdId);
if (BN_CLICKED != nNc)
{
break;
}
//按下按钮后会一直处于hilit状态,需要清除一下
PostMessage(hWnd, BM_SETSTATE, 0, 0);
keySound();
switch (nCmdId)
{
case ID_PUSHBUTTON_COMMON_PASSWORD :/*密码*/
{
/*省略业务逻辑*/
}
/*省略其余控件*/
default:
{
break;
}
}
break;
}
case MSG_LBUTTONDOWN:
{
static int pre_x, pre_y;
pre_x = LOWORD (lParam);
pre_y = HIWORD (lParam);
break;
}
case MSG_DESTROY:
{
sg_hPasswordDialog = 0;
SetIMEStatus(IME_STATUS_ENABLED, FALSE);
SetIMEStatus(IME_STATUS_AUTOTRACK, FALSE);
break;
}
case MSG_CLOSE:
{
EndDialog(hDlg, 0);
break;
}
}
return DefaultDialogProc (hDlg, nMessage, wParam, lParam);
}
这个回调函数很长,但可以分成几个部分来看
首先是在页面生成的时候会按顺序执行MSG_CREATE
、MSG_INITDIALOG
、MSG_PAINT
内语句,MSG_INITDIALOG
一般进行业务逻辑的初始化,MSG_PAINT
内进行页面内控件的绘制;
以绘制文字、绘制图片、绘制纯色矩形为例介绍,代码如下
/*绘制文字*/
hWnd = GetDlgItem(hDlg, ID_STATIC_PRIVATE_PASSWORD_CLICKED_PICTURE);
if (hWnd)
{
SelectFont (hdc, default_font[MAIN_FONT_SIZE_17]);
GetWindowRect(hWnd, &rc);
DrawText(hdc, "一户一密码", -1, &rc, DT_LEFT| DT_VCENTER );
}
/*绘制图片*/
FillBoxWithBitmap(hdc,200,72,
bmp_setting[xxx].bmWidth, bmp_setting[xxx].bmHeight,
&bmp_setting[xxx]);
/*绘制纯色矩形*/
SetBrushColor(hdc, RGB2Pixel (HDC_SCREEN, 0xCE, 0xC9, 0xC9));
FillBox(hdc,0,59,272,1);
再回到回调函数uiPasswordProc
,然后根据不同控件nCmdId的触发,调用switch函数选择性的执行MSG_COMMAND
内的指令,在执行命令后会再次调用MSG_PAINT
对界面进行刷新重绘