我要飞得更高系列一

    今天,距离我开始实习(2007.08.06)到工作马上就一年了,这一年中,我学到了很多东西,东西很杂,有时候自己都忘记了看过的一些东西。稀落算算,看得也有十几本书了,有的走马观花,有的爱不释手。不过这些书对我的成长起到了决定性的作用。所以在接下来的日子里,我要重温旧梦,达到更高的境界,因为愚人打算要飞得更高。

案例一,如何在vc中支持shell 以及dde

vc中,利用MFC建立的程序,在CMyAppInitInstance()中,增加EnableShellOpen(),以及RegisterShellFileTypes()。就可以支持双击打开,以及dde

为了支持 dde, 跟到代码中可以看到

void CDocManager::RegisterShellFileTypes(BOOL bCompat)中有部分相关代码

……………………

                            // path/shell/open/ddeexec = [open("%1")]

                            strTemp.Format(_afxShellOpenFmt, (LPCTSTR)strFileTypeId,

                                   (LPCTSTR)_afxDDEExec);

                            if (!_AfxSetRegKey(strTemp, _afxDDEOpen))

……………………

于是,运行完后,可以看到在注册表中对应的程序文件中有如下键值:

HKEY_CLASSES_ROOT中对应有ddeexec对应键值[open(“% 1” )]

vcDOCMGR.CPP中有如下定义

AFX_STATIC_DATA const TCHAR _afxShellOpenFmt[] = _T("%s//shell//open//%s");

AFX_STATIC_DATA const TCHAR _afxShellPrintFmt[] = _T("%s//shell//print//%s");

AFX_STATIC_DATA const TCHAR _afxShellPrintToFmt[] = _T("%s//shell//printto//%s");

AFX_STATIC_DATA const TCHAR _afxDefaultIconFmt[] = _T("%s//DefaultIcon");

AFX_STATIC_DATA const TCHAR _afxShellNewFmt[] = _T("%s//ShellNew");

 

#define DEFAULT_ICON_INDEX 0

 

AFX_STATIC_DATA const TCHAR _afxIconIndexFmt[] = _T(",%d");

AFX_STATIC_DATA const TCHAR _afxCommand[] = _T("command");

AFX_STATIC_DATA const TCHAR _afxOpenArg[] = _T(" /"%1/"");

AFX_STATIC_DATA const TCHAR _afxPrintArg[] = _T(" /p /"%1/"");

AFX_STATIC_DATA const TCHAR _afxPrintToArg[] = _T(" /pt /"%1/" /"%2/" /"%3/" /"%4/"");

AFX_STATIC_DATA const TCHAR _afxDDEArg[] = _T(" /dde");

 

AFX_STATIC_DATA const TCHAR _afxDDEExec[] = _T("ddeexec");

AFX_STATIC_DATA const TCHAR _afxDDEOpen[] = _T("[open(/"%1/")]");

AFX_STATIC_DATA const TCHAR _afxDDEPrint[] = _T("[print(/"%1/")]");

AFX_STATIC_DATA const TCHAR _afxDDEPrintTo[] = _T("[printto(/"%1/",/"%2/",/"%3/",/"%4/")]");

 

AFX_STATIC_DATA const TCHAR _afxShellNewValueName[] = _T("NullFile");

AFX_STATIC_DATA const TCHAR _afxShellNewValue[] = _T("");

支持注册表的注册。

关于DDE,首先从WM_DDE_EXECUTE消息开始,在CFrameWnd中有如下消息映射

       ON_MESSAGE(WM_DDE_INITIATE, OnDDEInitiate)

       ON_MESSAGE(WM_DDE_EXECUTE, OnDDEExecute)

       ON_MESSAGE(WM_DDE_TERMINATE, OnDDETerminate)

 

OnDDEExecute中会触发

if (!AfxGetApp()->OnDDECommand(szCommand))

 

于是,最终调用到BOOL CDocManager::OnDDECommand(LPTSTR lpszCommand)中,不过这里有点需要注意的情况:

// always ACK the execute command - even if we do nothing

LRESULT CFrameWnd::OnDDEExecute(WPARAM wParam, LPARAM lParam)

{

       // unpack the DDE message

       UINT unused;

       HGLOBAL hData;

       VERIFY(UnpackDDElParam(WM_DDE_EXECUTE, lParam, &unused, (UINT*)&hData));

 

       // get the command string

       TCHAR szCommand[_MAX_PATH * 2];

       LPCTSTR lpsz = (LPCTSTR)GlobalLock(hData);

       lstrcpyn(szCommand, lpsz, _countof(szCommand));

       GlobalUnlock(hData);

 

       // acknowledge now - before attempting to execute

       ::PostMessage((HWND)wParam, WM_DDE_ACK, (WPARAM)m_hWnd,

              ReuseDDElParam(lParam, WM_DDE_EXECUTE, WM_DDE_ACK,

              (UINT)0x8000, (UINT)hData));

 

       // don't execute the command when the window is disabled

       if (!IsWindowEnabled())

       {

              TRACE1("Warning: DDE command '%s' ignored because window is disabled./n",

                     szCommand);

              return 0;

       }

 

       // execute the command

       if (!AfxGetApp()->OnDDECommand(szCommand))

              TRACE1("Error: failed to execute DDE command '%s'./n", szCommand);

 

       return 0L ;

}

以上是VC6.0的源码,不过在VS2003中,这里有个错误,即漏掉了语句

lstrcpyn(szCommand, lpsz, _countof(szCommand));所以对DDE的支持失败。

注:可以从CodeGuru上找到类似的说明。

解决方法: 在自己的CMainFrame中重写

ON_MESSAGE(WM_DDE_EXECUTE, OnDDEExecute)

以及 OnDDEExecute函数。

案例二,关于CScrollView

感觉这里好像有个bug,就是在

SetScrollSizes()后调用ScrollToPosition()。如果doc的大小明显小于ViewClientRect时,那么ScrollToPosition()中的参数不管设多少,其返回ScrollPosition不为零。

感觉很是奇怪,最后的解决办法在自己在调用ScrollToPosition时提前判断一下,viewRect的大小是否大于DocRect来解决问题的。

你可能感兴趣的:(我要飞得更高系列一)