1.当用SubClass的方法,使一个CWnd的类与一个HWND的句柄联系在一起之后,CWnd的类会首先调用这个函数进行预先的处理,你可以重载以便处理自己的要预先准备的数据!
子类化:就是将一个HWND的句柄中的WndProc用SetWindowLong的方法替换为由CWnd的AfxWndProc;然后用类的方法处理HWND;2.是WINDOW在绘制时的有效区域,可以自己改动大小!3.当有一些消息需要在传递给消息处理函数之前,先作些处理时就可以用,不过也经常有一些需要监测消息的功能和其他一些自定义的功能需要在这里处理!
直接通过ClassWizard就可进行重载,也可手工添加:
//在.h文件的class 声明中添加;
virtual BOOL PreTranslateMessage(MSG* pMsg);
//在.cpp文件中添加函数体:BOOL CMyWnd::PreTranslateMessage(MSG* pMsg)
{
// TODO: Add your specialized code here and/or call the base class return CBaseWnd::PreTranslateMessage(pMsg);
}4.当你不想让窗口用缺省的方式(DefWindowProc)绘制底色的时,就重载!
直接通过ClassWizard响应WM_ERASEBKGND即可;
或者手工:
//在.h文件的class 声明中添加
afx_msg BOOL OnEraseBkgnd(CDC* pDC);
//在.cpp文件的消息映射表中添加
BEGIN_MESSAGE_MAP(CMyWnd, CBaseWnd)
...
ON_WM_ERASEBKGND() // 添加的行
...
END_MESSAGE_MAP()
//在.cpp中添加函数;
BOOL CMyWnd::OnEraseBkgnd(CDC* pDC)
{
// TODO: Add your message handler code here and/or call default
return CBaseWnd::OnEraseBkgnd(pDC);
}5.直接的效果就是使TextOut,DrawText等文字输出函数的在该DC上输出的文字没有文字的背景,只有文字的颜色!同时生效的还有网格画刷!对某些类型的Pen也有类似效果!6.是用来判断鼠标的位置处于WINDOWS的哪个位置,比如:
是否Window的Caption?
是否Window的Border(上下左右)?
是否Window的Client Region?
是否Window的左上角,右下角...
等!
子类化:就是将一个HWND的句柄中的WndProc用SetWindowLong的方法替换为由CWnd的AfxWndProc;然后用类的方法处理HWND;2.是WINDOW在绘制时的有效区域,可以自己改动大小!3.当有一些消息需要在传递给消息处理函数之前,先作些处理时就可以用,不过也经常有一些需要监测消息的功能和其他一些自定义的功能需要在这里处理!
直接通过ClassWizard就可进行重载,也可手工添加:
//在.h文件的class 声明中添加;
virtual BOOL PreTranslateMessage(MSG* pMsg);
//在.cpp文件中添加函数体:BOOL CMyWnd::PreTranslateMessage(MSG* pMsg)
{
// TODO: Add your specialized code here and/or call the base class return CBaseWnd::PreTranslateMessage(pMsg);
}4.当你不想让窗口用缺省的方式(DefWindowProc)绘制底色的时,就重载!
直接通过ClassWizard响应WM_ERASEBKGND即可;
或者手工:
//在.h文件的class 声明中添加
afx_msg BOOL OnEraseBkgnd(CDC* pDC);
//在.cpp文件的消息映射表中添加
BEGIN_MESSAGE_MAP(CMyWnd, CBaseWnd)
...
ON_WM_ERASEBKGND() // 添加的行
...
END_MESSAGE_MAP()
//在.cpp中添加函数;
BOOL CMyWnd::OnEraseBkgnd(CDC* pDC)
{
// TODO: Add your message handler code here and/or call default
return CBaseWnd::OnEraseBkgnd(pDC);
}5.直接的效果就是使TextOut,DrawText等文字输出函数的在该DC上输出的文字没有文字的背景,只有文字的颜色!同时生效的还有网格画刷!对某些类型的Pen也有类似效果!6.是用来判断鼠标的位置处于WINDOWS的哪个位置,比如:
是否Window的Caption?
是否Window的Border(上下左右)?
是否Window的Client Region?
是否Window的左上角,右下角...
等!
HOWTO: SubClass the MDIClient by Using MFC
Last reviewed: October 23, 1998
Article ID: Q129471
--------------------------------------------------------------------------------The information in this article applies to:
The Microsoft Foundation Classes (MFC) included with:
- Microsoft Visual C++ for Windows, versions 1.0, 1.5, 1.51, 1.52
- Microsoft Visual C++, 32-bit Edition, versions 1.0, 2.0, 2.1,
4.0, 4.1, 4.2, 5.0, 6.0
SUMMARY
In MFC, the MDICLIENT window is stored in a public HWND member variable (m_hwndMDIClient) within the CMDIFrameWnd class. CMDIFrameWnd is the base class of the CMainFrame class in an AppWizard-generated MDI application. There are three steps required to subclass the MDICLIENT window:
Use ClassWizard to derive a class from CWnd called CMDIClientWnd. Add the function, GetSuperWndProcAddr(), to CMDIClientWnd. Use CMDIClientWnd to subclass the MDICLIENT window. Once the MDICLIENT window has been subclassed with CMDIClientWnd, message handlers and other functions can be placed in the CMDIClientWnd class.
MORE INFORMATION
Here is more detailed information about each of the steps:
Use ClassWizard to derive a class from CWnd called CMDIClientWnd.
For details on how to derive a class using ClassWizard, please see the User's Guide documentation on ClassWizard, specifically the "Adding a New Class" section.
Add the function GetSuperWndProcAddr() to CMDIClientWnd.
NOTE: This step need only be performed if you are using 16-bit versions of Visual C++, not 32-bit. The 32-bit versions of Visual C++ implement this functionality for you. Once the class has been created, add the following prototype to the header file: public:
WNDPROC* GetSuperWndProcAddr(); And add the following function to the .CPP file: WNDPROC* CMDIClientWnd::GetSuperWndProcAddr() {
static WNDPROC NEAR pfnSuper = NULL;
return &pfnSuper;
}Use CMDIClientWnd to subclass the MDICLIENT window in the CMDIFrameWnd class (usually CMainFrame).
To the CMainFrame class, add a public variable of type CMDIClientWnd called m_wndMDIClient. Then modify OnCreate for CMainFrame as follows: int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CMDIFrameWnd::OnCreate(lpCreateStruct) == -1)
return -1; if (!m_wndMDIClient.SubclassWindow (m_hWndMDIClient)) { // Add
TRACE ("Failed to subclass MDI client window\n"); // Add
return (-1); // Add
} // Add
...
}
After completing these three steps, you can use ClassWizard to add message handlers to CMDIClientWnd similar to the one below, which changes the MDICLIENT's background color.
BOOL CMDIClientWnd::OnEraseBkgnd(CDC* pDC) { // Set brush to desired background color
CBrush backBrush(RGB(255, 128, 128)); // Save old brush
CBrush* pOldBrush = pDC->SelectObject(&backBrush); CRect rect;
pDC->GetClipBox(&rect); // Erase the area needed pDC->PatBlt(rect.left, rect.top, rect.Width(), rect.Height(),
PATCOPY);
pDC->SelectObject(pOldBrush);
return TRUE;} Keywords : MfcMisc kbvc600 kbvc500 kbvc410 kbvc420 kbvc100 kbvc150 kbvc152 kbvc200 kbMFC kbprg kbtool
Technology : kbMfc
Version : 1.0 1.5 1.52 2.0 4.1 4.2 5.0 6.0
Platform : NT WINDOWS
Issue type : kbhowto
--------------------------------------------------------------------------------
================================================================================
THE INFORMATION PROVIDED IN THE MICROSOFT KNOWLEDGE BASE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. MICROSOFT DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MICROSOFT CORPORATION OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER INCLUDING DIRECT, INDIRECT, INCIDENTAL, CONSEQUENTIAL, LOSS OF BUSINESS PROFITS OR SPECIAL DAMAGES, EVEN IF MICROSOFT CORPORATION OR ITS SUPPLIERS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES SO THE FOREGOING LIMITATION MAY NOT APPLY. Last reviewed: October 23, 1998
© 1998 Microsoft Corporation. All rights reserved. Terms of Use.
void CMyView::OnDraw(CDC* pDC)
{
CRgn rgnNew;
//获得指定的rgn,实际应用中可将rgn的获得通过函数封装起来,以便更具有灵活性!
rgnNew.CreateRectRgn(10, 10, 300, 100); //将得到的rgn用RGN_COPY的方式选择到当前的DC中,就使的所有不再这个rgn区域内的绘制代码都无效,看不到!
//当然如果使用RGN_AND,RGN_XOR,RGN_OR,RGN_DIFF等就会有不同的效果!
pDC->SelectClipRgn(&rgnNew, RGN_COPY);
rgnNew.DeleteObject();
}
当然上述的代码也可以在一次绘制的过程中不断的变动Rgn,不断的进行SelectClipRgn的动作,以产生更灵活的应用!3.比如给当前的窗口(CMyWnd)添加加速键的处理!
int CMyWnd::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
...
m_hAccel = ::LoadAccelerators(hCurrentInst, IDR_MYACCEL);
...
}
BOOL CMyWnd::PreTranslateMessage(MSG* pMsg)
{
// TODO: Add your specialized code here and/or call the base class
if(m_hAccel)
{
if(::TranslateAccelerator(GetSafeHwnd(), m_hAccel, pMsg))
return TRUE;
}
return CBaseWnd::PreTranslateMessage(pMsg);
}4.
BOOL CMyWnd::OnEraseBkgnd(CDC* pDC)
{
// TODO: Add your message handler code here and/or call default
return TRUE;//返回TRUE,不再继续擦WINDOW的背景!
// return CBaseWnd::OnEraseBkgnd(pDC);
}5.void CMyView::OnDraw(CDC* pDC)
{
...
CString strOutput("Text output!");
pDC->TextOut(10, 10, strOutput);
pDC->SetBkMode(TRANSPARENT);
pDC->TextOut(10, 100, strOutput);
//两次的效果不同;
...
}6.在MSDN中搜索OnNcHittest关键字,在C++Q&A中找到的例子!
Figure 13 Fixing the Buggy Title Bar
////////////////////////////////////////////////////////////////
// Copyright 1996 Microsoft Systems Journal.
// If this program works, it was written by Paul DiLascia.
// If not, I don't know who wrote it.
// This program compiles with Visual C++ 4.1 on Windows 95
//
// MONITOR shows how to create a main window that is only a title bar,
// and how to prevent Windows from drawing size cursors in up/down or
// left/right directions
//
#include "StdAfx.h"
#include "TraceWin.h"////////////////
// Remove this comment to see the original bug
//
//#define BUG//////////////////
// Standard application class
//
class CMonitorApp : public CWinApp {
public:
CMonitorApp() : CWinApp() { }
virtual BOOL InitInstance();
};//////////////////
// Monitor window is main frame
//
class CMonitorWindow : public CFrameWnd {
public:
CMonitorWindow();
afx_msg void OnTimer(UINT nIdEvent);
afx_msg void OnPaint();
afx_msg UINT OnNcHitTest(CPoint point);
DECLARE_MESSAGE_MAP()
}; CMonitorApp theApp;//////////////////
// Initialize app: create main window
//
BOOL CMonitorApp::InitInstance()
{
MfxTraceInit();
m_pMainWnd = new CMonitorWindow;
m_pMainWnd->ShowWindow(m_nCmdShow);
m_pMainWnd->UpdateWindow();
return TRUE;
} BEGIN_MESSAGE_MAP(CMonitorWindow, CFrameWnd)
ON_WM_TIMER()
ON_WM_PAINT()
ON_WM_NCHITTEST()
END_MESSAGE_MAP() //////////////////
// Create monitor window. Constructor actually creates window too.
//
CMonitorWindow::CMonitorWindow()
{
// Compute size of window: smallest to display text
CString s = _T("Memory: 100%% used [Phys:999999K total/999999K free]");
CWindowDC dc(NULL); // screen DC
CSize sz = dc.GetTextExtent(s, s.GetLength()); // size of text
sz.cx += 2*GetSystemMetrics(SM_CXSMICON) + // plus icon, close box,
2*GetSystemMetrics(SM_CXSIZEFRAME); // and sizable frame
sz.cy += 2*GetSystemMetrics(SM_CYFIXEDFRAME); // should be SIZEFRAME, but
// it doesn't matter
CreateEx(WS_EX_TOPMOST, NULL, NULL,
#ifdef BUG
// The buggy version uses WS_BORDER to disallow sizing,
// resulting in a frame that's too narrow.
WS_BORDER
#else
// The fix uses WS_THICKFRAME to get the fat border, but
// disallows sizing by trapping WM_NCHITTEST
WS_THICKFRAME
#endif
| WS_CAPTION | WS_SYSMENU,
CW_USEDEFAULT,
CW_USEDEFAULT,
sz.cx,
sz.cy,
NULL, 0); TRACE("Desired size = %d x %d\n", sz.cx, sz.cy);
CRect rc;
GetWindowRect(&rc);
TRACE("Actual size = %d x %d\n", rc.Width(), rc.Height());
GetClientRect(&rc);
TRACE("Client size = %d x %d\n", rc.Width(), rc.Height()); TRACE("Minimum window height = %d\n", GetSystemMetrics(SM_CYMIN));
TRACE("Caption height = %d\n", GetSystemMetrics(SM_CYCAPTION));
TRACE("Sizable border height = %d\n",GetSystemMetrics(SM_CYSIZEFRAME));
TRACE("Non-sizable border height = %d\n",
GetSystemMetrics(SM_CYFIXEDFRAME)); SetTimer((UINT) 1, (UINT) 7500, NULL);
OnTimer(1); // first update immediately
}//////////////////
// Update the window caption by getting new memory stats
//
void CMonitorWindow::OnTimer(UINT nIdEvent)
{
MEMORYSTATUS ms;
ms.dwLength = sizeof(MEMORYSTATUS);
GlobalMemoryStatus(&ms);
CString s;
s.Format(_T("Memory: %2ld%% used [Phys:%ldK total/%ldK free]"),
ms.dwMemoryLoad,
ms.dwTotalPhys>>10,
ms.dwAvailPhys>>10);
SetWindowText(s);
}//////////////////
// Handle WM_NCCHITTEST:
// Re-map top/bottom to HTBORDER, and corners to HTLEFT or HTRIGHT
//
UINT CMonitorWindow::OnNcHitTest(CPoint point)
{
UINT nRet = CFrameWnd::OnNcHitTest(point);
#ifndef BUG
switch (nRet) {
case HTTOP:
case HTBOTTOM:
return HTBORDER;
case HTTOPLEFT:
case HTBOTTOMLEFT:
return HTLEFT;
case HTTOPRIGHT:
case HTBOTTOMRIGHT:
return HTRIGHT;
}
#endif
return nRet;
}//////////////////
// Paint client red to make it contrast more with frame/caption
//
void CMonitorWindow::OnPaint()
{
CPaintDC dc(this);
CRect rc;
GetClientRect(&rc);
CBrush b(RGB(255,0,0)); // red
CBrush* pOldBrush = dc.SelectObject(&b);
dc.PatBlt(rc.left, rc.top, rc.Width(), rc.Height(), PATCOPY);
dc.SelectObject(pOldBrush);
}
HBRUSH CCtrlDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
// TODO: Change any attributes of the DC here
if (nCtlColor==CTLCOLOR_BTN ){
static CBrush brush(RGB(20,90,123));
pDC->SetBkColor(RGB(20,90,123));
pDC->SetTextColor(RGB(256,256,256));
return HBRUSH(brush);
}
// TODO: Return a different brush if the default is not desired
return hbr;
}
3.最后问一下,我的msdn中的mfc sample例子程序均不能安装,总是在“click to open or copy XXX project files"连接后,弹出插入msdn光盘的提示,但插入光盘后却"找不到帮助文件“。你的msdn例子程序能否运行?
1.需要.lib文件(一般与.dll捆在一起),在setting->link->object/dll moudle上
把它加入。
在其它机器上,不需注册,但你需要与你的.exe捆在一起
2.OnCtlColor()不能改变CButton的color,你需:
class CMyButton::publi CButton;
然後再重载CMyButton::DrawItem()来改变Color
3.需要Copy到你的盘上
hope will get your technical support again!! i am edwardyi!