积累的VC编程小技巧之工具提示

1.用鼠标移动基于对话框的无标题栏程序的简单方法

void CVCTestDlg::OnLButtonDown(UINT nFlags, CPoint point) 
{
    //一句话解决问题 
    SendMessage(WM_SYSCOMMAND,0xF012,0);
    CDialog::OnLButtonDown(nFlags, point);
}

2.对话框消息映射

有对话框A,B
从A中发消息给B然后B处理。
准备工作,先定义消息,如下
#define WM_B_NOTIFY WM_USER + 300

首先,必须将B的对话框句柄传送给A,暂时叫m_hWndB;

在A的发送消息的地方这样写:
::SendMessage( m_hWndB,WM_B_NOTIFY,TRUE,NULL );

这样A中的处理就完了,下面说B 中的
首先定义消息处理函数,如下
void B::ModiNotify( WPARAM wParam, LPARAM lParam )
{
    MessageBox("小样,我就不信,搞不定你!");
}

然后加消息隐射,如下:
BEGIN_MESSAGE_MAP(CB, CDialog)
    //{{AFX_MSG_MAP(CRPServerDlg)

ON_MESSAGE( WM_B_NOTIFY,ModiNotify )

//}}AFX_MSG_MAP
END_MESSAGE_MAP()

3.如何改变框对话或窗体视窗的背景颜色

调用CWinApp : : SetDialogBkColor可以改变所有应用程序的背景颜色。第一个参数指定了背景颜色,第二个参数指定了文本颜色。下例将应用程序对话设置为蓝色背景和黄色文本。
BOOL CSampleApp : : InitInstance ( )
{

//use blue dialog with yellow text .
SetDialogBkColor (RGB (0, 0, 255 ), RGB ( 255 , 255 , 0 ) ) ;

}
需要重画对话(或对话的子控件)时,Windows向对话发送消息WM_CTLCOLOR,通常用户可以让Windows选择绘画背景的刷子,也可重置该消息指定刷子。下例说明了创建一个红色背景对话的步骤。
首先,给对话基类增加一人成员变量CBursh :
class CMyFormView : public CFormView
{

private :
CBrush m_ brush ; // background brush

} ;
其次, 在类的构造函数中将刷子初始化为所需要的背景颜色。
CMyFormView : : CMyFormView ( )
{
// Initialize background brush .
m_brush .CreateSolidBrush (RGB ( 0, 0, 255 ) )
}
最后,使用ClassWizard处理WM_CTLCOLOR消息并返回一个用来绘画对话背景的刷子句柄。注意:由于当重画对话控件时也要调用该函数,所以要检测nCtlColor参量。
HBRUSH CMyFormView : : OnCtlColor (CDC* pDC , CWnd*pWnd , UINT nCtlColor )
{
// Determine if drawing a dialog box . If we are , return +handle to
//our own background brush . Otherwise let windows handle it .
if (nCtlColor = = CTLCOLOR _ DLG )
return (HBRUSH) m_brush .GetSafeHandle ( ) ;
return CFormView : : OnCtlColor (pDC, pWnd , nCtlColor );
}

4.如何实现点一下对话框外面的区域,自动隐藏对话框?

[问题提出]
    如果想在点击对话框外面的地方使得对话框关闭,该如何做?

[解决方法]
    试试下面的代码,原理是在激活对话框时,捕获鼠标的动作,当鼠标点击时判断是否点击在对话框外,是的话就释放对话框.

[程序实现]
    建立名为My的对话框程序.实现如下步骤:
    在MyDlg.h中加入:

class CShowWindow1Dlg : public CDialog
    {
     // Construction
     public:
         int m_cx;
         int m_cy;
         ......
    };

在MyDlg.cpp中:

//定义消息映象,处理鼠标单击及激活
    BEGIN_MESSAGE_MAP(CMyDlg, CDialog)
        //{{AFX_MSG_MAP(CMyDlg)
        ON_WM_LBUTTONDOWN()
        ON_WM_ACTIVATE()
        //}}AFX_MSG_MAP
    END_MESSAGE_MAP()

void CMyDlg::OnLButtonDown(UINT nFlags, CPoint point)
    {
        CRect rect;
        GetClientRect(&rect);
        rect.InflateRect(m_cx, m_cy);
  
        //Release dialog if the user click outside it.
        if(!rect.PtInRect(point))
        {
           EndDialog(IDCANCEL);
        }

CDialog::OnLButtonDown(nFlags, point);
    }

void CMyDlg::OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized)
    {
        CDialog::OnActivate(nState, pWndOther, bMinimized);

if( nState == WA_ACTIVE || nState == WA_CLICKACTIVE)
            SetCapture();
        else
            ReleaseCapture();
    }

BOOL CMyDlg::OnInitDialog()
    {
        CDialog::OnInitDialog();
        .....
        
        OSVERSIONINFO info;
        memset((char*)&info, 0, sizeof(OSVERSIONINFO));
        info.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
        if(GetVersionEx(&info))
        {  //we don't run on Win32s, so check only two values
           if(info.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
           {  //On windows 95
              m_cx = GetSystemMetrics(SM_CXFIXEDFRAME);
              m_cy = GetSystemMetrics(SM_CYFIXEDFRAME);
           }
           else
           {  //On NT
              m_cx = GetSystemMetrics(SM_CXDLGFRAME);
              m_cy = GetSystemMetrics(SM_CYDLGFRAME);
           }
        }
    }

说明:
     1)WM_ACTIVATE消息在ClassWizard中没有,按如下步骤添加,右击CMyDlg类,选Add Windows Message Handle,接着在Filter for messages available to中选Window,在New Windows messages/events列表中就会出现WM_ACTIVATE,选中,点击Add Handler
     2)SM_CXDLGFRAME,SM_CYDLGFRAME   NT中取得有WS_DLGFRAMEstyle风格的窗口的高和宽 95中已经废弃而采用SM_CX_FIXEDFRAME和SM_CYFIXEDFRAME

5.如何使FormView中显示dialog时,不是凹的

[问题提出]
  为什么FormView中显示dialog时,是凹的,能不能不这样
  [解决方法]
  在Dialog的属性中:
    增加属性WS_BORDER   或者 WS_EX_WINDOWEDGE
  用程序实现:
  pView->ModifyStyle(,WS_BORDER) 或者pView->ModifyStyleEx(,WS_EX_WINDOWEDGE )

6.对话框上建立View的方法

OnInitDialog()
{
  CDialog:;OnInitDialog();

CRect rectWindows;
GetWinodwRect(&rectWindows);
CRuntimeClass *pViewClass=RUNTIME_CLASS(CXXXView);
CCreateContext *pContext=new CCreateContext;
pContext->m_pCurrentDoc=NULL;
pContext->m_pCurrentFrame=NULL;
pContext->m_pLastView=NULL;
pContext->m_pNewDocTemplate=NULL;
pContext->m_pNewViewClass=pViewClass;

CWnd *pWnd=DYNAMIC_DOWNCAST(CWnd,pviewClass->CreateObject());
pWnd->Create(NULL,NULL,AFX_WS_DEFAULT_VIEW,CRect(0,0,0,0),this,pContext);
delete pContext;
CXXXView *pView=DYUNAMIC_DOWNCAST(CXXXView,pWnd);
...............
}

7.模态对话框初始显示位置的控制

正确的方法是在OnInitDialog中添加MoveWindow,如: 
     MoveWindow(0, 1, 300, 200); 
    需要注意的是前两个参数不能都为0。如果你确实希望把窗口放在(0, 0)处,可以在对话框设计窗口的属性中选中Absolute Align,然后再加入 
     MoveWindow(0, 0, 300, 200); 
    为什么会是这样?你看了MFC的源程序就会明白。原来MFC在调用你的OnInitDialog之后,会调用CDialog::CheckAutoCenter()(在dlgcore.cpp中)检查是否需要将窗口居中,你看了这个函数后就明白为什么需要上面那么做了。

8.动态修改对话框的大小

[问题提出]
    关于如何动态改变对话框的大小,我做了个Demo,大家看看.

[程序实现]
     //本函数使用方法: 
     //第一个参数:如果是TRUE表示显示扩展的对话框,如果是FALSE,表示缩小对话框。 
     //第二个参数:表示本对话框的HWND, 
     //第三个参数:表示缩小后大小的控件的ID
    void COptionDlg::ExpandBox(BOOL fExpand, HWND hwnd, int nIDDefaultBox)
    {
         CWnd *pWndBox=GetDlgItem(nIDDefaultBox);
         RECT rcDefaultBox,rcChild,rcIntersection,rcWnd;
         pWndBox->GetWindowRect(&rcDefaultBox);
         HWND hwndChild = ::GetTopWindow(hwnd);
         for (; hwndChild != NULL; hwndChild = ::GetNextWindow(hwndChild,GW_HWNDNEXT)) 
         {
                  ::GetWindowRect(hwndChild, &rcChild);
                  if (!IntersectRect(&rcIntersection, &rcChild, &rcDefaultBox))
                           ::EnableWindow(hwndChild, fExpand);
         }
         ::GetWindowRect(hwnd, &rcWnd);
         if (GetWindowLong(hwnd, GWL_USERDATA) == 0)
         {
                  SetWindowLong(hwnd, GWL_USERDATA,
                           MAKELONG(rcWnd.right - rcWnd.left, 
                           rcWnd.bottom - rcWnd.top));
                  ::ShowWindow(pWndBox->m_hWnd, SW_HIDE);
         }
         ::SetWindowPos(hwnd, NULL, 0, 0,
                  rcDefaultBox.right - rcWnd.left,
                  rcDefaultBox.bottom - rcWnd.top,
                  SWP_NOZORDER | SWP_NOMOVE);
         if(fExpand)
         {
                  DWORD dwDims = GetWindowLong(hwnd, GWL_USERDATA);
                  ::SetWindowPos(hwnd, NULL, 0, 0,
                           LOWORD(dwDims), HIWORD(dwDims), SWP_NOZORDER | SWP_NOMOVE);
                  ::SendMessage(hwnd, DM_REPOSITION, 0, 0);
         }
    }

9.隐藏对话框窗口(窗口没有焦点时)

在程序启动时InitDialog中使用SetWindowPos将窗体设置到屏幕以外
然后再隐藏
1.在OnInitDialog()函数里设置定时器:(WINDOWS   API里面响应消息WM_INITDIALOG)   
  SetTimer(1,   1,   NULL);   
  2.添加处理WM_TIMER的消息处理函数OnTimer,添加代码:    
  if(nIDEvent   ==   1)    
  {   
      DeleteTimer(1);   
      ShowWindow(SW_HIDE);    
  }

10.如何实现点击对话框外的地方使对话框到主窗口的后面

将桌面做为父窗口
pMDlg = new CMDlg;
pMDlg->Create(IDD_M_DIALOG,CWnd::GetDesktopWindow()/* 设置父窗口 */);
pMDlg->ShowWindow(SW_SHOW); 
然后在任务栏里隐藏对话框程序
如何让对话框应用程序在在任务栏上不出现,并且不隐藏窗口。
[解决方法]
   把对话框的扩展属性修改成为WS_EX_TOOLWINDOW。
[程序实现]
   把对话框的属性设置成为toolwindow,然后在需要的地方执行本代码。
   DWORD Style = ::GetWindowLong(AfxGetMainWnd()->m_hWnd,GWL_EXSTYLE);
   Style = WS_EX_TOOLWINDOW ;
   AfxGetMainWnd()->ShowWindow(FALSE);
   ::SetWindowLong(AfxGetMainWnd()->m_hWnd,GWL_EXSTYLE,Style); 
   AfxGetMainWnd()->ShowWindow(TRUE);

11.怎么让无模式对话框显示在主窗口后面

要解决这个问题的关键在于CDialog的Create并不能建立一个无属主的窗口.必须用另外方式建窗口.   
    
  比如你的对话框类叫CDlgNoOwner,在CMainFrame中加一个CDlgNoOwner类的成员变量,   
  弹出这个对话框的消息处理函数为   
    
  void   CMainFrame::OnNoowner()     
  {

CDlgNoOwner   *m_dlgTest=new   CDlgNoOwner(this);  
      HWND   hwndDlg=::CreateDialog( AfxGetInstanceHandle(),MAKEINTRESOURCE(                              CDlgNoOwner::IDD),NULL/*owner*/,NULL/*dlgproc*/);
      //注意此处DLGPROC为NULL,并不要紧,因为接下要subclass啦   
      m_dlgTest->SubclassWindow   (hwndDlg);//挂接到成员变量!   
      m_dlgTest->ShowWindow   (SW_SHOW);   
      //这时可以看到一个"*"的对话框弹出,和你的主窗口是平起平坐的.   
  }   
    
  当然不要忘了在对话框关闭时DestroyWindow()..那都是在对话框类中的标准处理了.

12.如何得到屏幕的真实尺寸(以对话框为例)

[问题提出]
我的屏幕是1024*800,如何得到屏幕的真实大小,我用GetSystemMetrics(SM_CYFULLSCREEN)得到的高度总是小于800
[问题解答]
GetSystemMetrics(SM_CYFULLSCREEN)得到的只是屏幕用户区的大小。要得到屏幕的真实大小需要使用
GetDeviceCaps函数,该API函数原型是这样的:

int GetDeviceCaps(
  HDC hdc,     // handle to DC
  int nIndex   // index of capability
);
///得到屏幕尺寸的代码如下
void CMyDlg::OnPaint() 
{
   CPaintDC dc(this); 
   int cx = ::GetDeviceCaps(dc.m_hDC,HORZRES);///得到宽度
   int cy = ::GetDeviceCaps(dc.m_hDC,VERTRES);///得到高度
   CDialog::OnPaint();

}

13.如何在对话框中加入工具条

在 OnInitDialog 中加入下面代码:

BOOL CYourDlg::OnInitDialog()

{

CDialog::OnInitDialog();

// Create the toolbar. To understand the meaning of the styles used, you

// can take a look at the MSDN for the Create function of the CToolBar class.

ToolBar.Create(this, WS_CHILD | WS_VISIBLE | CBRS_TOP | CBRS_TOOLTIPS |CBRS_FLYBY | CBRS_BORDER_BOTTOM);

// I have assumed that you have named your toolbar's resource as IDR_TOOLBAR1.

// If you have given it a different name, change the line below to accomodate

// that by changing the parameter for the LoadToolBar function.

ToolBar.LoadToolBar(IDR_TOOLBAR1);

CRect rcClientStart;

CRect rcClientNow;

GetClientRect(rcClientStart);

// To reposition and resize the control bar

RepositionBars(AFX_IDW_CONTROLBAR_FIRST, AFX_IDW_CONTROLBAR_LAST,0, reposQuery, rcClientNow);

CPoint ptOffset(rcClientNow.left - rcClientStart.left,rcClientNow.top-rcClientStart.top);

CRect rcChild;

CWnd* pwndChild = GetWindow(GW_CHILD);

while (pwndChild)

{

pwndChild->GetWindowRect(rcChild);

ScreenToClient(rcChild);

rcChild.OffsetRect(ptOffset);

pwndChild->MoveWindow(rcChild, FALSE);

pwndChild = pwndChild->GetNextWindow();

}

CRect rcWindow;

GetWindowRect(rcWindow);

rcWindow.right += rcClientStart.Width() - rcClientNow.Width();

rcWindow.bottom += rcClientStart.Height() - rcClientNow.Height();

MoveWindow(rcWindow, FALSE);

// And position the control bars

RepositionBars(AFX_IDW_CONTROLBAR_FIRST, AFX_IDW_CONTROLBAR_LAST, 0);

return TRUE;  // return TRUE  unless you set the focus to a control

}

14.如何改变对话框的形状

可用下面一些涵数:

 CreatePolygonRgn
     CreateRectRgn
     CreateRoundRectRgn 
.

  CRgn m_rgn;  // Put this in your dialog's header file. i.e. a member variable
 
  // This Gets the size of the Dialog: This piece of code is to be placed in the
  // OnInitDialog Function of your dialog.
 
  CRect rcDialog
  GetClientRect(rcDialog);
 
  // The following code Creates the area and assigns it to your Dialog
  m_rgn.CreateEllipticRgn(0, 0, rcDialog.Width(), rcDialogHeight());
  SetWindowRgn(GetSafeHwnd(), (HRGN) m_rgn, TRUE);

15.如何在对话框中加入状态条

定义 CStatusBar 变量:

CStatusBar m_StatusBar;

定义状态条指定状态:

static UINT BASED_CODE indicators[] =

{

ID_INDICATOR_CAPS,

ID_INDICATOR_NUM

};

在 OnInitDialog 中加入下面代码:

m_StatusBar.CreateEx(this,SBT_TOOLTIPS,WS_CHILD|WS_VISIBLE|CBRS_BOTTOM,AFX_IDW_STATUS_BAR);

// Set the indicators namely caps and nums lock status

m_StatusBar.SetIndicators(indicators,sizeof(indicators)/sizeof(UINT));

CRect rect;

GetClientRect(&rect);

m_StatusBar.SetPaneInfo(0,ID_INDICATOR_CAPS,SBPS_NORMAL,rect.Width()/2);

m_StatusBar.SetPaneInfo(1,ID_INDICATOR_NUM,SBPS_STRETCH ,rect.Width()/2);

RepositionBars(AFX_IDW_CONTROLBAR_FIRST,AFX_IDW_CONTROLBAR_LAST,ID_INDICATOR_NUM);

m_StatusBar.GetStatusBarCtrl().SetBkColor(RGB(180,180,180));

16.如何实现非客户区移动

可用下面二种方法:

// Handler for WM_LBUTTONDOWN message

void CYourDialog::OnLButtonDown(UINT nFlags, CPoint point)

{

CDialog::OnLButtonDown(nFlags, point);

PostMessage( WM_NCLBUTTONDOWN, HTCAPTION, MAKELPARAM( point.x, point.y));

}

// Handler for WM_NCHITTEST message

LONG CYourDialog::OnNcHitTest( UINT uParam, LONG lParam )

{

int xPos = LOWORD(lParam);

int yPos = HIWORD(lParam);

UINT nHitTest = CDialog::OnNcHitTest(CSize(xPos, yPos));

return (nHitTest == HTCLIENT) ? HTCAPTION : nHitTest;

}

17.如何使对话框初始为最小化状态

在 OnInitDialog 中加入下面代码:

SendMessage(WM_SYSCOMMAND, SC_MAXIMIZE, NULL);

18.如何限定对话框大小范围

在 WM_SIZING中加入下面代码:

void CYourDialog::OnSizing(UINT fwSide, LPRECT pRect)

{

if(pRect->right - pRect->left <=200)

pRect->right = pRect->left + 200;

if(pRect->bottom - pRect->top <=200)

pRect->bottom = pRect->top + 200;

CDialog::OnSizing(fwSide, pRect);

}

上一篇:Matlab图像处理系列2———空间域平滑滤波器


下一篇:iOS开发之让你的应用“动”起来