WEB开发网
开发学院软件开发VC 解说Win32的窗口子类化 阅读

解说Win32的窗口子类化

 2010-07-11 20:44:50 来源:WEB开发网   
核心提示:这样一来,这个对话框就会和MSN一样,解说Win32的窗口子类化(2),在单击了“关闭”之后,就会完成最小化的工作了,这样才能用GetDlgItem获得它的句柄来完成子类化;2、你必须为它设置SS_NOTIFY样式,以保证在单击它的时候它能够通知父窗口对话框;3、单击它打开网页的处理也可以放在子

这样一来,这个对话框就会和MSN一样,在单击了“关闭”之后,就会完成最小化的工作了。那么,对于窗口过程已定义好的系统控件,将如何手动响应它的消息呢?

我们可以用函数指针的办法,将我们感兴趣的消息拦截下来,处理完之后再让预定义的窗口过程处理。这个过程大致如下:

WNDPROC OldProc;
  OldProc = (WNDPROC)SetWindowsLong(hWnd, GWL_WNDPROC, (LONG)NewProc);

当然,这里的新窗口过程NewProc是预先由你实现好的。上述代码执行以后,系统在处理hWnd的窗口消息时,就会先进入你实现的NewProc回调过程,然后在处理过你感兴趣的消息之后,通过CallWindowProc函数和你预先保存的OldProc再次回到原来的回调过程中完成剩余的工作。

以上就是窗口子类化的原理分析,下面我通过一个实例来实际解说如何对窗口进行子类化。这个例子的界面如下:

界面上方的编辑框是用来限制浮点输入的,下面则是一个普通的超级链接。

好了,下面我开始按步骤完成对这两个窗口的子类化:

第一步,在主窗口对话框初始化的时候,保存原有的窗口过程,并设置新的窗口过程。代码如下:

case WM_INITDIALOG:
  EditProc = (WNDPROC)SetWindowLong(GetDlgItem(hDlg, IDC_EDIT), GWL_WNDPROC, (LONG)ProcFloat);
  StaticProc = (WNDPROC)SetWindowLong(GetDlgItem(hDlg, IDC_ST_HOMEPAGE), GWL_WNDPROC, (LONG)ProcLink);
  break;

第二步,实现浮点编辑框的窗口过程:

LRESULT CALLBACK ProcFloat(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
 if (Msg == WM_CHAR && wParam != ''.'' && (wParam <= ''0'' || wParam >= ''9'') && wParam != VK_BACK)
 {
  MessageBeep(MB_OK);
  return 0;
 }
 else
  return CallWindowProc(EditProc, hWnd, Msg, wParam, lParam);
}

这里需要解释的是,由于控件本身的需求,所以只需要拦截一个消息,就是接收字符的WM_CHAR。当用户输入的字符不是小数点、0~9以及退格键(注意不要少了退格键,否则你将会发现你的编辑框无法删除输入错误的数字)的时候,就发出一声声音以提示输入错误。至于其它的消息,则调用原有的回调函数进行处理。

第三步,实现超级链接的窗口过程:

LRESULT CALLBACK ProcLink(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
 switch (Msg)
 {
 case WM_SETCURSOR:
  SetCursor(LoadCursor(NULL, IDC_HAND));
  break;
 case WM_LBUTTONDOWN:
  ShellExecute(NULL, "open", "http://home.ncust.edu.cn/~titilima", NULL, NULL, SW_SHOWNORMAL);
  break;
 default:
  return CallWindowProc(StaticProc, hWnd, Msg, wParam, lParam);
 }
 return 0;
}

这段代码很容易明白:它完成了两件事,其一是设置光标指针为手形(注意:对于较早的Windows系统,是没有预定义的IDC_HAND指针的,这个时候你需要在EXE的资源中自己画一个手形指针,比如Delphi之中的手形指针就是自己画的),其二是当单击了鼠标左键的时候打开你想打开的网页链接。

其实对于超级链接,它更主要的东西是在子类化之外实现的——就是它的字体颜色(注意这段代码是在主窗口对话框的回调过程中实现的):

case WM_CTLCOLORSTATIC:
  if (GetDlgItem(hDlg, IDC_ST_HOMEPAGE) == (HWND)lParam)
  {
   SetTextColor((HDC)wParam, 0xff0000);
   SetBkMode((HDC)wParam, TRANSPARENT);
   return (LRESULT)CreateSolidBrush(GetSysColor(COLOR_BTNFACE));
  }
  break;

还有几点要说明的是:

1、你的这个Static超链接必须拥有一个唯一的资源ID,比如我的这个就是IDC_ST_HOMEPAGE,这样才能用GetDlgItem获得它的句柄来完成子类化;

2、你必须为它设置SS_NOTIFY样式,以保证在单击它的时候它能够通知父窗口对话框;

3、单击它打开网页的处理也可以放在子类化之外,处理主窗口对话框的WM_COMMAND消息也可以实现这一功能。

本文配套源码

上一页  1 2 

Tags:解说 Win 窗口

编辑录入:爽爽 [复制链接] [打 印]
赞助商链接