UG二次开发:用MFC对话框模拟UG对话框

做过UG二次开发的都知道,在UG里做二次开发的主要界面就是对话框了,UG自己定义了一套二次开发的界面接口,即所谓的UIStyler,对于我们用惯了MFC及Windows的消息机制来说,它那点简单的事件映射,仅有的几个控件(好像连常用的树控件都没有)让我们没有发挥的余地。于是使用MFC对话框代替UG的对话框是每个从MFC进入UG二次开发的人的首先想法。关于怎么在UG中使用MFC对话框已经有文章讲过了,我这里就不再讲了。但MFC对话框的一个很大的缺点就是与UG对框的风格不统一。UG的对话框都具有统一的风格,首先,按钮都具有自己的风格,比如它的四个角是圆角,鼠标移到上面会显示一个Focus的框。然后它的所有对话框都是一级一级弹出来的,比如点击OK按钮,可能会弹出下一个对话框,而上一级对话框会隐藏掉,按Back按钮会重新返回到上一个对话框。再有,一旦有另外一个对话框弹出,当前的对话框都会隐藏或销毁。

下面就给出我的仿UG对话框风格的对话框类CHsPMEDialog,它除了实现了上面的三点UG风格外,由于UG似乎对键盘消息做了截获,如果是普通的MFC对话框,在UG内使用时一些特殊的功能键就无效了,比如TAB键、回车键、ESC都无效了。为此在我的类中,还使用了键盘钩子截获这几个按键消息并做出处理。

//-----------------------------------------------------------------------------
// 描述:可实现类似UG风格OK、Cancel、Apply按钮风格的按钮类
//    该类来自网络,稍作修改,版权归原作者所有
//-----------------------------------------------------------------------------
class CHsPMEButton : public CButton
{
 // Construction
public:
 CHsPMEButton();
 
 // Attributes
public:
 
 // Operations
public:
 inline void SetNormalTopColor(COLORREF color)
 {
  m_NormalColorTop = color;
 }
 inline void SetNormalBottomColor(COLORREF color)
 {
  m_NormalColorBottom = color;
 }
 inline void SetActiveTextColor(COLORREF color)
 {
  m_ActiveTextColor = color;
 }
 inline void SetNormalTextColor(COLORREF color)
 {
  m_NormalTextColor = color;
 }
 inline void SetSelectTextColor(COLORREF color)
 {
  m_SelectTextColor = color;
 }
 inline void SetFrameColor(COLORREF color)
 {
  m_FrameColor = color;
 }
 inline void SetActiveColor(COLORREF color)
 {
  m_ActiveColor = color;
 }
 // Overrides
 // ClassWizard generated virtual function overrides
 //{{AFX_VIRTUAL(CHsPMEButton)
protected:
 virtual void PreSubclassWindow();
 //}}AFX_VIRTUAL
 
 // Implementation
public:
 virtual ~CHsPMEButton();
 
 // Generated message map functions
protected:
 //{{AFX_MSG(CHsPMEButton)
 afx_msg void OnMouseMove(UINT nFlags, CPoint point);
 //}}AFX_MSG
 
 void DrawFace(COLORREF Top, COLORREF Bottom, CRect& rc, CRect CalRc, CDC* pDC);
 void DrawFrame(COLORREF HeightLight, COLORREF ShadowLight, COLORREF FrameColor, CRect& rc, CDC* pDC);
 void DrawItem( LPDRAWITEMSTRUCT lpDrawItemStruct );
 LONG OnMouseLeave(WPARAM, LPARAM);
 BOOL m_bIsMouseMove;
 
 COLORREF m_FrameColor;
 COLORREF m_ActiveColor;
 
 COLORREF m_ActiveTextColor;
 COLORREF m_NormalTextColor;
 COLORREF m_SelectTextColor;
 
 COLORREF m_FrameHeight;
 COLORREF m_FrameShadow;
 
 COLORREF m_NormalColorTop;
 COLORREF m_NormalColorBottom;
 
 DECLARE_MESSAGE_MAP()
};

/
// CHsPMEButton

CHsPMEButton::CHsPMEButton()
{
 m_bIsMouseMove = 0;

 m_NormalTextColor = RGB(0, 0, 0);
 m_SelectTextColor = RGB(0, 0, 0);
 m_ActiveTextColor = RGB(0, 0, 0);

 //m_ActiveColor  = RGB(250, 180, 80);
 m_ActiveColor  = RGB(255, 120, 80);

 m_NormalColorTop = RGB(255, 255, 255);  // 从UG对话框中取出的颜色
 m_NormalColorBottom = RGB(213, 208, 196);

 m_FrameColor  = RGB(0, 64, 128);
 m_FrameHeight  = RGB(230, 230, 230);
 m_FrameShadow  = RGB(128, 128, 128);
}

CHsPMEButton::~CHsPMEButton()
{
}


BEGIN_MESSAGE_MAP(CHsPMEButton, CButton)
 //{{AFX_MSG_MAP(CHsPMEButton)
 ON_WM_MOUSEMOVE()
 //}}AFX_MSG_MAP
 ON_MESSAGE(WM_MOUSELEAVE,OnMouseLeave)
END_MESSAGE_MAP()

/
// CHsPMEButton message handlers

void CHsPMEButton::DrawItem( LPDRAWITEMSTRUCT lpDrawItemStruct )
{
 //*
 CDC* pDC      = CDC::FromHandle(lpDrawItemStruct->hDC);
 DWORD nState  = lpDrawItemStruct->itemState;
 DWORD nAction = lpDrawItemStruct->itemAction;
 CRect rc   = lpDrawItemStruct->rcItem;
 UINT uStyle   = DFCS_BUTTONPUSH;

 pDC->SetBkMode(TRANSPARENT);
 CString strText;
 GetWindowText(strText);

 if( nState & ODS_SELECTED )
 {
  m_bIsMouseMove = 0;

  DrawFace(m_NormalColorBottom, m_NormalColorTop, rc, rc, pDC);
  DrawFrame(m_FrameShadow, m_FrameShadow, m_FrameColor, rc, pDC); 
  //pDC->Draw3dRect(rc, RGB(0,0,0), RGB(0,0,0));

  pDC->SetTextColor(m_SelectTextColor);
 }
 else //Normal
 {
  DrawFace(m_NormalColorTop, m_NormalColorBottom, rc, rc, pDC);
  DrawFrame(m_FrameHeight, m_FrameShadow, m_FrameColor, rc, pDC);

  pDC->SetTextColor(m_NormalTextColor);
 }

 if( m_bIsMouseMove )
 {
  CRect rc2(rc);
  rc2.DeflateRect(2, 2, 2, 2);

  DrawFace(RGB(GetRValue(m_ActiveColor), GetGValue(m_ActiveColor)+100, GetBValue(m_ActiveColor)+100),
   m_ActiveColor, rc, rc, pDC);
  DrawFace(m_NormalColorTop, m_NormalColorBottom, rc2, rc, pDC);

  CBrush NullBrush;
  NullBrush.CreateStockObject(NULL_BRUSH);
  CBrush* pOldBrush = pDC->SelectObject(&NullBrush);
  
  CPen Pen;
  Pen.CreatePen(PS_SOLID, 1, m_FrameColor);
  CPen* pOldPen = pDC->SelectObject(&Pen);
  rc.InflateRect(1,1,1,1);
  pDC->RoundRect(rc, CPoint(3, 3));
  //rc.DeflateRect(1, 1, 1, 1);
  //pDC->Draw3dRect(rc, HeightLight, ShadowLight);
  
  pDC->SelectObject(pOldPen);
  pDC->SelectObject(pOldBrush);

  pDC->SetTextColor(m_ActiveTextColor);
 }
 
 pDC->DrawText(strText, strText.GetLength(),
  &lpDrawItemStruct->rcItem, DT_SINGLELINE|DT_VCENTER|DT_CENTER);
 //*///
}

void CHsPMEButton::OnMouseMove(UINT nFlags, CPoint point)
{
 // TODO: Add your message handler code here and/or call default
 if( m_bIsMouseMove == 0 )
 {
  m_bIsMouseMove = 1;
  Invalidate();
  
  TRACKMOUSEEVENT trackmouseevent;
  trackmouseevent.cbSize = sizeof(trackmouseevent);
  trackmouseevent.dwFlags = TME_LEAVE;
  trackmouseevent.hwndTrack = GetSafeHwnd();
  trackmouseevent.dwHoverTime = HOVER_DEFAULT;
  _TrackMouseEvent(&trackmouseevent);
 }
 
 CButton::OnMouseMove(nFlags, point);
}

LONG CHsPMEButton::OnMouseLeave(WPARAM, LPARAM)
{
 m_bIsMouseMove = 0;
 Invalidate();

 return 0;
}

void CHsPMEButton::PreSubclassWindow()
{
 // TODO: Add your specialized code here and/or call the base class
 UINT nBS = GetButtonStyle();

 // Add BS_OWNERDRAW style
 SetButtonStyle(nBS | BS_OWNERDRAW);

 CButton::PreSubclassWindow();
}

void CHsPMEButton::DrawFace(COLORREF Top, COLORREF Bottom, CRect& rc, CRect CalRc, CDC* pDC)
{
 CPen Pen;
 CPen* pOldPen = pDC->SelectObject(&Pen);
 
 int R, G, B;
 R = (GetRValue(Top) - GetRValue(Bottom)) / CalRc.Height();
 G = (GetGValue(Top) - GetGValue(Bottom)) / CalRc.Height();
 B = (GetBValue(Top) - GetBValue(Bottom)) / CalRc.Height();
 
 //R = R>0 ? R : -R;
 //G = G>0 ? G : -G;
 //B = B>0 ? B : -B;

 int ColR = GetRValue(Top), ColG = GetGValue(Top), ColB = GetBValue(Top);
 COLORREF ColMax = Top > Bottom ? Top : Bottom;
 COLORREF ColMin = Top > Bottom ? Bottom: Top;

 for(int i=0; i {
  ColR -= R;
  ColG -= G;
  ColB -= B;

  /*
  if( ColR >= GetRValue(ColMax) || ColR <= GetRValue(ColMin) ||
   ColG >= GetGValue(ColMax) || ColG <= GetGValue(ColMin) ||
   ColB >= GetBValue(ColMax) || ColB <= GetBValue(ColMin) )
  {
   R = G = B = 0;
  }///*/


  Pen.DeleteObject();
  Pen.CreatePen(PS_SOLID, 1, RGB(ColR, ColG, ColB));
    
  pDC->SelectObject(&Pen);
  
  pDC->MoveTo(rc.left, rc.top+i);
  pDC->LineTo(rc.right, rc.top+i);
 }

 pDC->SelectObject(pOldPen);
}

void CHsPMEButton::DrawFrame(COLORREF HeightLight, COLORREF ShadowLight, COLORREF FrameColor, CRect& rc, CDC* pDC)
{
 CBrush NullBrush;
 NullBrush.CreateStockObject(NULL_BRUSH);
 CBrush* pOldBrush = pDC->SelectObject(&NullBrush);

 CPen Pen;
 Pen.CreatePen(PS_SOLID, 1, FrameColor);
 CPen* pOldPen = pDC->SelectObject(&Pen);
 
 pDC->RoundRect(rc, CPoint(3, 3));
 rc.DeflateRect(1, 1, 1, 1);
 pDC->Draw3dRect(rc, HeightLight, ShadowLight);

 pDC->SelectObject(pOldPen);
 pDC->SelectObject(pOldBrush);
}


/
// CHsPMEDialog dialog
//-----------------------------------------------------------------------------
// 描述:此类可作为仿照UG UIStyler对话框的基类。它模仿了以下几种风格:
//    1、实现UG对话框的后退(Back)功能。实现方法为任何对话框在调出下一级
//   (非模式)对话框时,先隐藏自身在需要返回上一级对话框时,根据其父窗口
//   指针将其显示出来,然后隐藏或销毁自身
//    2、实现类似UG "OK"、"Apply"、"Back"、"Cancel"等按钮的XP按钮风格效果。
//    采用的方法为使用上面的CHsPMEButton作为按钮的基类
//    3、由于UG系统对键盘消息的控制,使得某些键盘消息不能发送到MFC对话框,
//    如:TAB键,ESC键,ENTER键。而这些键对于对话框来说是很重要的。
//    采用的方法为键盘钩子,对本进程(即UG进程)的键盘消息进行截获。
//    4、实现非模态对话框类似UG风格,即只要其它对话框弹出来,上一个对话框
//    就自动销毁(隐藏)。采用CBT钩子方法截获窗口创建消息。
//-----------------------------------------------------------------------------
// 注意:
// 1、在构造对话框时必须给出其父窗口指针
// 2、在初始化基类时必须指定对话框资源模板ID
// 3、对话框资源中必须提供ID为IDC_BACK的按钮
// 4、派生类必须重写OnOK及OnCancel并且调用本基类的OnOK与OnCancel
//-----------------------------------------------------------------------------

class CHsPMEDialog : public CDialog
{
 DECLARE_DYNAMIC(CHsPMEDialog)    // 为了实现IsKindOf功能
// Construction
public:
 CHsPMEDialog(UINT nIDTemplate, CWnd* pParent = NULL);   // standard constructor
 ~CHsPMEDialog();
 BOOL Create(CWnd *pParent = NULL);
 
// Dialog Data
 //{{AFX_DATA(CHsPMEDialog)
 //enum { IDD = _UNKNOWN_RESOURCE_ID_ };
  // NOTE: the ClassWizard will add data members here
 //}}AFX_DATA


// Overrides
 // ClassWizard generated virtual function overrides
 //{{AFX_VIRTUAL(CHsPMEDialog)
 protected:
 virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
 virtual void OnOK();
 virtual void OnCancel();
 virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam);
 virtual LRESULT DefWindowProc(UINT message, WPARAM wParam, LPARAM lParam);
 //}}AFX_VIRTUAL

// Implementation
protected:

 // Generated message map functions
 //{{AFX_MSG(CHsPMEDialog)
 afx_msg void OnBack();
 virtual BOOL OnInitDialog();
 afx_msg void OnDestroy();
 //}}AFX_MSG
 DECLARE_MESSAGE_MAP()

protected:
 // attributes
 CWnd   *m_pParent;     // 父窗口指针
 HICON   m_hIcon;     // 图标
 UINT   m_nTemplateID;    // 对话框资源模板ID

 CHsPMEButton m_btOK;
 CHsPMEButton m_btCancel;
 CHsPMEButton m_btBack;

 static HHOOK m_hkKeyboard;    // 键盘钩子句柄
 HHOOK   m_hkCBT;     // CBT钩子句柄
 
 //-------------------------------------------------------------------------
 // 为了能判断最上层窗口是不是一个CHsPMEDialog窗口,将建立一个所有CHsPMEDialog
 // 对象的链表,通过遍历链表就能知道是不是此类窗口。下面两个成员函数分别为
 // 链表的头及下一个结点的指针
 static CHsPMEDialog* m_spHead;
 CHsPMEDialog *m_pNext;

 // operations
 // 键盘钩子消息的处理函数
 static LRESULT CALLBACK KeyboardProc(
  int code,       // hook code
  WPARAM wParam,  // virtual-key code
  LPARAM lParam   // keystroke-message information
  );
 // CBT钩子消息处理函数
 static LRESULT CALLBACK CBTProc(
  int nCode,      // hook code
  WPARAM wParam,  // depends on hook code
  LPARAM lParam   // depends on hook code
  );
 

 // 在对象列表中查找以确定指定窗口是否为CHsPMEDialog窗口
 static BOOL  IsWndKindOfThis(HWND hWnd);
 // 取得指定虚拟内存地址所在的模块句柄(即其内存基地址)
 static HMODULE ModuleFromAddress(PVOID pv);
public:
 // attributes

 // operations
 // 用于模仿UG的创建一个子对话框,同时隐藏父对话框
 BOOL CreateChildDialog(CHsPMEDialog *pChild);
};


CHsPMEDialog* g_pHsPMEDlg = NULL;
CHsPMEDialog* CHsPMEDialog::m_spHead = NULL;
HHOOK CHsPMEDialog::m_hkKeyboard = NULL;

IMPLEMENT_DYNAMIC(CHsPMEDialog, CDialog)

CHsPMEDialog::CHsPMEDialog(UINT nIDTemplate, CWnd* pParent /*=NULL*/)
 : CDialog(nIDTemplate, pParent)
{
 //{{AFX_DATA_INIT(CHsPMEDialog)
  // NOTE: the ClassWizard will add member initialization here
 //}}AFX_DATA_INIT
 m_pParent = pParent;
 m_nTemplateID = nIDTemplate;
 m_hIcon = AfxGetApp()->LoadIcon(IDI_ICON_UG); // UG对话框特有图标

 // 建立起链表
 m_pNext = m_spHead;
 m_spHead = this;
 m_hkCBT = NULL;
}

CHsPMEDialog::~CHsPMEDialog()
{
 // 从链表中删除本结点
 CHsPMEDialog *pTemp = m_spHead;
 if(pTemp == this)
 {
  m_spHead = pTemp->m_pNext;
 }
 else
 {
  for(; pTemp->m_pNext != NULL; pTemp = pTemp->m_pNext)
  {
   if(pTemp->m_pNext == this)
   {
    pTemp->m_pNext = pTemp->m_pNext->m_pNext;
    break;
   }
  }
 }
}

void CHsPMEDialog::DoDataExchange(CDataExchange* pDX)
{
 CDialog::DoDataExchange(pDX);
 //{{AFX_DATA_MAP(CHsPMEDialog)
 DDX_Control(pDX, IDOK, m_btOK);
 DDX_Control(pDX, IDCANCEL, m_btCancel);
 DDX_Control(pDX, IDC_BACK, m_btBack);
 //}}AFX_DATA_MAP
}


BEGIN_MESSAGE_MAP(CHsPMEDialog, CDialog)
 //{{AFX_MSG_MAP(CHsPMEDialog)
 ON_BN_CLICKED(IDC_BACK, OnBack)
 ON_WM_DESTROY()
 //}}AFX_MSG_MAP
END_MESSAGE_MAP()

/
// CHsPMEDialog message handlers

BOOL CHsPMEDialog::Create(CWnd *pParent /* = NULL */)
{
 m_pParent = pParent;
 return CDialog::Create(m_nTemplateID, pParent);
}


BOOL CHsPMEDialog::OnInitDialog()
{
 CDialog::OnInitDialog();

 // 设置标题栏图标
 SetIcon(m_hIcon, TRUE);
 SetIcon(m_hIcon, FALSE);
 
 // UG的对话框的几个标准按钮没有TAPSTOP
 CWnd *pWnd = NULL;
 pWnd = GetDlgItem(IDOK);
 if(pWnd)
 {
  pWnd->ModifyStyle(WS_TABSTOP, 0);
 }
 pWnd = GetDlgItem(IDC_BACK);
 if(pWnd)
 {
  pWnd->ModifyStyle(WS_TABSTOP, 0);
 }
 pWnd = GetDlgItem(IDCANCEL);
 if(pWnd)
 {
  pWnd->ModifyStyle(WS_TABSTOP, 0);
 }
 
 g_pHsPMEDlg = this;  // 方便在静态函数成员中调用

 // 设置键盘钩子
 if(m_hkKeyboard == NULL)
 {
  m_hkKeyboard = SetWindowsHookEx(WH_KEYBOARD, KeyboardProc, AfxGetInstanceHandle(), GetCurrentThreadId());
 }
 if(m_hkKeyboard == NULL)
 {
  TRACE("Set Keyboard Hook failed: %d/n", GetLastError());
 }

 if(m_hkCBT == NULL)
 {
  m_hkCBT = SetWindowsHookEx(WH_CBT, CBTProc, AfxGetInstanceHandle(), GetCurrentThreadId());
 }
 if(m_hkCBT == NULL)
 {
  TRACE("Set CBT Hook Failed: %u/n", GetLastError());
 }
 
 return TRUE;  // return TRUE unless you set the focus to a control
               // EXCEPTION: OCX Property Pages should return FALSE
}

void CHsPMEDialog::OnOK()
{
 CDialog::OnOK();
 if(m_pParent)
 {
  //m_pParent->DestroyWindow();
  //((CDialog*)m_pParent)->EndDialog(IDOK);
  ((CHsPMEDialog*)m_pParent)->OnOK();
 }
}

void CHsPMEDialog::OnCancel()
{
 CDialog::OnCancel();
 if(m_pParent)
 {
  //m_pParent->DestroyWindow();
  //((CDialog*)m_pParent)->EndDialog(IDCANCEL);
  ((CHsPMEDialog*)m_pParent)->OnCancel();
 }
}

void CHsPMEDialog::OnBack()
{
 if(m_pParent)
 {
  m_pParent->ShowWindow(SW_SHOW);
 }
 CDialog::OnCancel();
}


BOOL CHsPMEDialog::CreateChildDialog(CHsPMEDialog *pChild)
{
 BOOL bRet = FALSE;
 if(pChild->GetSafeHwnd() == NULL)
 {
  bRet = pChild->Create(this);
 }
 bRet &= ShowWindow(SW_HIDE);
 bRet &= pChild->ShowWindow(SW_SHOW);
 return bRet;
}

LRESULT CALLBACK CHsPMEDialog::KeyboardProc(int code, WPARAM wParam, LPARAM lParam)
{
 if(code == HC_ACTION && !(lParam & 0x80000000))  // 0x80000000表示keyup,即最高位为0表示keydown,为1表示keyup
 {
  //TRACE("Key down/n");
  CWnd *pTopWnd = CWnd::GetActiveWindow();
  if(pTopWnd && IsWndKindOfThis(pTopWnd->m_hWnd))
  {
   // 是上层窗口是CHsPMEDialog派生类窗口的键盘消息
   if(wParam == VK_TAB || wParam == VK_ESCAPE || wParam == VK_RETURN)
   {
    // 只截获tab、esc及回车键
    //g_pHsPMEDlg->PostMessage(WM_CHAR, wParam, lParam);
    //g_pHsPMEDlg->PostMessage(WM_KEYDOWN, wParam, lParam);
   }
   switch(wParam) {
   case VK_TAB:
    {
     CWnd *pWnd = pTopWnd->GetFocus();
     CWnd *pNext = pTopWnd->GetNextDlgTabItem(pWnd, FALSE);
     if(pNext)
     {
      int nCtrlID = pNext->GetDlgCtrlID();
      //TRACE("CtrlID = %d/n", nCtrlID);
      pWnd = pNext;
      while(pNext && nCtrlID == IDOK || nCtrlID == IDCANCEL || nCtrlID == IDC_BACK)
      {
       // 根据UG对话框的属性,这三个按钮是没有焦点的
       pNext = pTopWnd->GetNextDlgTabItem(pNext, FALSE);
       if(!pNext || pNext == pWnd)
       {
        // 对话框上只有上述三个按钮
        return CallNextHookEx(NULL, code, wParam, lParam);
       }
       nCtrlID = pNext->GetDlgCtrlID();
       //TRACE("CtrlID = %d/n", nCtrlID);
      }
      pNext->SetFocus();
     }
     //return TRUE;
    }
    break;
   case VK_ESCAPE:
    ((CHsPMEDialog*)pTopWnd)->EndDialog(IDCANCEL);
    //return TRUE;
    break;
   case VK_RETURN:
    // UG实际上并不处理回车键
    break;
   default:
    break;
   }
  }
 }
 return CallNextHookEx(NULL, code, wParam, lParam);
}

void CHsPMEDialog::OnDestroy()
{
 CDialog::OnDestroy();

 g_pHsPMEDlg = NULL;

 // 销毁键盘钩子
 if(m_hkKeyboard)
 {
  UnhookWindowsHookEx(m_hkKeyboard); 
  m_hkKeyboard = NULL;
 }

 if(m_hkCBT)
 {
  UnhookWindowsHookEx(m_hkCBT); 
  m_hkCBT = NULL;
 }
}

BOOL CHsPMEDialog::IsWndKindOfThis(HWND hWnd)
{
 CHsPMEDialog *pTemp = m_spHead;
 BOOL bFound = FALSE;
 for(; pTemp != NULL; pTemp = pTemp->m_pNext)
 {
  if(pTemp->m_hWnd == hWnd)
  {
   bFound = TRUE;
   break;
  }
 }
 return bFound;
}

// Returns the HMODULE that contains the specified memory address
HMODULE CHsPMEDialog::ModuleFromAddress(PVOID pv)
{
 
 MEMORY_BASIC_INFORMATION mbi;
 return((VirtualQuery(pv, &mbi, sizeof(mbi)) != 0)
  ? (HMODULE) mbi.AllocationBase : NULL);
}

LRESULT CHsPMEDialog::CBTProc(int nCode, WPARAM wParam, LPARAM lParam)
{
 if(nCode == HCBT_CREATEWND)
 {
  //TRACE("A Window is being created/n");
  LPCBT_CREATEWND lpCBT = (LPCBT_CREATEWND)lParam;
  //TRACE("Window Name = %s, Class Name = %s/n", lpCBT->lpcs->lpszName, lpCBT->lpcs->lpszClass);
  if((lpCBT->lpcs->style & WS_POPUP || lpCBT->lpcs->style == WS_POPUPWINDOW))
  {
   // 只对弹出窗口进行响应,而不对子窗口(WS_CHILD或WS_CHILDWINDOW)响应
   // 取得窗口处理过程内存地址
   DWORD dwUserData = ::GetWindowLong((HWND)wParam, GWL_WNDPROC);
   if(dwUserData)
   {
    HMODULE hMoudle = ModuleFromAddress((PVOID)dwUserData);
    char szUGPath[MAX_PATH] = {0}, szModulePath[MAX_PATH] = {0};
    GetModuleFileNameA(NULL, szUGPath, MAX_PATH);
    GetModuleFileNameA(hMoudle, szModulePath, MAX_PATH);
    TRACE("CreateWindow Frome Module: %s/n", szModulePath);
    TRACE("Window Name: %s/n", lpCBT->lpcs->lpszName);
    if(stricmp(szUGPath, szModulePath) == 0)
    {
     // 窗口处理过程位于UG EXE模块中,此窗口必定为UG特有风格窗口(UG的对话框属于此类)
     if(_tcslen(lpCBT->lpcs->lpszClass) ==0)
     {
      // 通常对话框没有指定窗口类名而使用默认的#32770(Dialog)
      if(g_pHsPMEDlg && (HWND)wParam != g_pHsPMEDlg->m_hWnd &&
       lpCBT && lpCBT->lpcs->hwndParent != g_pHsPMEDlg->m_hWnd)
      {
       // 窗口非本窗口或其子窗口
       g_pHsPMEDlg->OnCancel();
      }
     }
    }
   }
  }
 }
 return CallNextHookEx(NULL, nCode, wParam, lParam);
}

LRESULT CHsPMEDialog::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
 // 不做任何事情,只是把窗口处理过程放到创建对话框的模块内存中来
 
 return CDialog::WindowProc(message, wParam, lParam);
}

LRESULT CHsPMEDialog::DefWindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
 
 return CDialog::DefWindowProc(message, wParam, lParam);
}

 

你可能感兴趣的:(UG二次开发:用MFC对话框模拟UG对话框)