标签MFC下的文章

05月09, 2007

我的小程序NuTs Window Manger

管理程序最有趣的功能见第二张图片,上面的方块代表可见的窗口.虚线将区域分割成9块, 正中间那块是我们的桌面. 其余8块是桌面以外的区域. 看上图,有一个窗口(是资源管理器)被我移到了右上角上图最左边的方块是qq,最下方的长条是任务栏,任务栏上面的小方块是输入发在方块里面拖动鼠标可以移动方块所对应的窗口呵呵,有意思吧,这样可以将窗口 "放到别人够不着的地方"

阅读全文 »

03月10, 2007

MFC学习笔记#1

作为Windows的Framework需要解决的一个问题就是 消息映射 Message Mapping

Delphi中由于有编译器的支持,可以直接在用户编写的类中处理需要处理的消息:

procedure WMLButtonDown(var Message: TWMLButtonDown); message WM_LBUTTONDOWN;

在MFC中就比较复杂了. afx使用宏来实现Windows消息到处理函数的映射而没有使用会带 而外的开销:由于C++中实现虚函数需要一个分发表vtable,而无论子类是否重写父类的虚函数, 都需要4个字节的开销.在CWnd类中至少要处理100个以上的消息.这样设计会带来很大的问题.

afx用一组宏将用于消息映射的数据保存在类中.大概情况是:记录该类可以处理的Windows消息, 当消息来到时,对比自己可以处理的消息列表,如果可以处理,就交给列表中记录的函数来处理. 而这个函数就是我们自己些的.比如 OnLButtonDown等

afx.h 中声明了mfc中最基础的类

struct CRuntimeClass;                  // object type information

class CObject;                                // the root of all objects classes

class CException;                         // the root of all exceptions
          class CArchiveException;              // archive exception
          class CFileException;                 // file exception
          class CSimpleException;
           class CMemoryException;               // out-of-memory exception
           class CNotSupportedException; // feature not supported exception

class CFile;                              // raw binary file
          class CStdioFile;                     // buffered stdio text/binary file
          class CMemFile;                       // memory based file

// Non CObject classes
class CString;                                // growable string type
class CTimeSpan;                              // time/date difference
class CTime;                                  // absolute time/date
struct CFileStatus;                           // file status information
struct CMemoryState;                          // diagnostic memory support

class CArchive;                               // object persistence tool
class CDumpContext;                           // object diagnostic dumping

先看一下CRuntimeClass

struct CRuntimeClass
{
// Attributes
LPCSTR m_lpszClassName;//保存类名
int m_nObjectSize;//类对象大小
UINT m_wSchema; // schema number of the loaded class//是否可序列化
CObject* (PASCAL* m_pfnCreateObject)(); // 指向类的构造函数的指针

           //指向父类CRuntimeClass的指针
#ifdef _AFXDLL
CRuntimeClass* (PASCAL* m_pfnGetBaseClass)();
#else
CRuntimeClass* m_pBaseClass;
#endif

// Operations
CObject* CreateObject(); //动态创建
BOOL IsDerivedFrom(const CRuntimeClass* pBaseClass) const; //类型鉴别

// Implementation
void Store(CArchive& ar) const; //序列化
static CRuntimeClass* PASCAL Load(CArchive& ar, UINT* pwSchemaNum) ;//"反序列化"

// CRuntimeClass objects linked together in simple list
CRuntimeClass* m_pNextClass;               // linked list of registered classes //注册类列表
};

CRuntimeClass 是MFC中很重要的一个类,动态创建实例是最常用的功能之一

// Helper macros for declaring CRuntimeClass compatible classes

#ifdef _AFXDLL
#define DECLARE_DYNAMIC(class_name) \
protected: \
static CRuntimeClass* PASCAL _GetBaseClass(); \
public: \
static const AFX_DATA CRuntimeClass class##class_name; \
virtual CRuntimeClass* GetRuntimeClass() const; \

#define _DECLARE_DYNAMIC(class_name) \
protected: \
static CRuntimeClass* PASCAL _GetBaseClass(); \
public: \
static AFX_DATA CRuntimeClass class##class_name; \
virtual CRuntimeClass* GetRuntimeClass() const; \

#else
#define DECLARE_DYNAMIC(class_name) \
public: \
static const AFX_DATA CRuntimeClass class##class_name; \
virtual CRuntimeClass* GetRuntimeClass() const; \

#define _DECLARE_DYNAMIC(class_name) \
public: \
static AFX_DATA CRuntimeClass class##class_name; \
virtual CRuntimeClass* GetRuntimeClass() const; \

#endif

// not serializable, but dynamically constructable
#define DECLARE_DYNCREATE(class_name) \
DECLARE_DYNAMIC(class_name) \
static CObject* PASCAL CreateObject();

#define _DECLARE_DYNCREATE(class_name) \
_DECLARE_DYNAMIC(class_name) \
static CObject* PASCAL CreateObject();

#define DECLARE_SERIAL(class_name) \
_DECLARE_DYNCREATE(class_name) \
AFX_API friend CArchive& AFXAPI operator>>(CArchive& ar, class_name* &pOb);

CObject 基本服务:

BOOL IsSerializable() const;
BOOL IsKindOf(const CRuntimeClass* pClass) const; //类型鉴别

// Overridables
virtual void Serialize(CArchive& ar); //序列化

// Diagnostic Support //诊断支持
virtual void AssertValid() const;
virtual void Dump(CDumpContext& dc) const;

//动态创建,利用CRuntimeClass里的m_pfnCreateObject
CObject* CRuntimeClass::CreateObject()

CWnd 在afxwin.h中定义,在wincore.cpp中实现 CWnd封装的功能

// Window tree access
// Message Functions
// Message processing for modeless dialog-like windows
// Window Text Functions
// CMenu Functions - non-Child windows only
// Window Size and Position Functions
// Coordinate Mapping Functions
// Update/Painting Functions
// Timer Functions
// ToolTip Functions
// Window State Functions
// Dialog-Box Item Functions
// Scrolling Functions
// Window Access Functions
// Alert Functions
// Clipboard Functions
// Caret Functions
// Shell Interaction Functions
// Icon Functions
// Context Help Functions
// Dialog Data support
// Help Command Handlers
// Layout and other functions
// OLE control wrapper functions

/* 消息处理函数 */
// Window-Management message handler member functions
// Nonclient-Area message handler member functions
// System message handler member functions
// Input message handler member functions
// Initialization message handler member functions
// Clipboard message handler member functions
// Control message handler member functions
// MDI message handler member functions
// Menu loop notification messages

Windows 控件的实现文件在 winctrl1.cpp~winctrl7.cpp

阅读全文 »

02月16, 2007

在MFC中使用ON_COMMAND_EX_RANGE宏

问题: 有时候我们希望用一个函数处理一系列的菜单命令

分析: 在处理菜单命令的函数中必须能知道菜单的ID; 以前用过ON_COMMANDRANGE宏; 在afxmsg.h中发现有个ON_COMMAND_EX宏;

解决:

BEGIN_MESSAGE_MAP(CClassName, CBaseClass)
   ...
ON_COMMAND_EX_RANGE(ID_MENUITEM_FIRST,ID_MENUITEM_FIRST, OnMenuItemClicked)
...
//}}AFX_MSG_MAP
END_MESSAGE_MAP()

因为

#define ON_COMMAND_EX_RANGE(id, idLast, memberFxn) \
{ WM_COMMAND, CN_COMMAND, (WORD)id, (WORD)idLast, AfxSig_bw, \
   (AFX_PMSG)(BOOL (AFX_MSG_CALL CCmdTarget::*)(UINT))&memberFxn },

而且

enum AfxSig{
   ...
    AfxSig_bw = AfxSig_bb,       // BOOL (UINT)
   ...
}

所以

BOOL CClassName::OnMiWlToSubDesk(UINT nID) 
{
   int nMenuIndex = nID - ID_MENUITEM_FIRST;
   return TRUE;
}

阅读全文 »

02月15, 2007

VC中响应未定义的消息

问题: 在MFC程序中需要响应显示器分辨率变化

分析: 如果分辨率变化会产生消息并发送给所有程序,那么只要响应该消息就可以了

解决: 通过在winuser.h中搜索DISPLAY找到

#define WM_DISPLAYCHANGE                 0x007E

由于VC的ClassWizard无法自动生成响应处理该消息的成员函数, 所以要手工增加消息映射

在afxmsg_.h中找到

#define ON_MESSAGE(message, memberFxn) \
{ message, 0, 0, 0, AfxSig_lwl, \
   (AFX_PMSG)(AFX_PMSGW) \
   (static_cast< LRESULT (AFX_MSG_CALL CWnd::*)(WPARAM, LPARAM) > \
   (memberFxn)) },

所以可以在相应的类中增加消息映射和函数:

函数:

// Generated message map functions
//{{AFX_MSG(CNuTsWMDlg)
virtual BOOL OnInitDialog();
...
afx_msg void OnDislayChanged(WPARAM wParam,LPARAM lParam);
...
//}}AFX_MSG
DECLARE_MESSAGE_MAP()

消息映射: ``c++ BEGIN_MESSAGE_MAP(CNuTsWMDlg, CDialog) //{{AFX_MSG_MAP(CNuTsWMDlg) ... ON_MESSAGE(WM_DISPLAYCHANGE,OnDislayChanged) ... //}}AFX_MSG_MAP END_MESSAGE_MAP() ```

阅读全文 »