積累的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);
}
RFID管理系統集成商 RFID中間件 條碼系統中間層 物聯網軟件集成