VC小知识总结(二)-------经典

作者在 2009-03-09 09:18:04 发布以下内容

(16)如何使用COleClientItem的IDispatch接口?
我创建了一个如何使用COleClientItem对象,我想使用它的自动化方法.有什么方法来获得IDispatch的接口?我试过以CCmdTarget为基类的的GetIDispatch函数但却出错,我用过EnableAutomation和GetIDispatch,却什么也没得到.

MSDN中有一篇关于这个的文章(TN039).如下的代码也可能是你所需要的:

LPDISPATCH CMyClientItem::GetIDispatch()
{
     ASSERT_VALID(this);
     ASSERT(m_lpObject != NULL);

     LPUNKNOWN lpUnk = m_lpObject;

     Run(); // must be running

     LPOLELINK lpOleLink = NULL;
     if (m_lpObject->QueryInterface(IID_IOleLink,
         (LPVOID FAR*)&lpOleLink) == NOERROR)
     {
         ASSERT(lpOleLink != NULL);
         lpUnk = NULL;
         if (lpOleLink->GetBoundSource(&lpUnk) != NOERROR)
         {
             TRACE0("Warning: Link is not connected!\n");
             lpOleLink->Release();
             return NULL;
         }
         ASSERT(lpUnk != NULL);
     }

     LPDISPATCH lpDispatch = NULL;
     if (lpUnk->QueryInterface(IID_IDispatch, &lpDispatch)
         != NOERROR)
     {
         TRACE0("Warning: does not support IDispatch!\n");
         return NULL;
     }

     ASSERT(lpDispatch != NULL);
     return lpDispatch;
}

(17)关于用户自定义的消息使用?
我写了一个基于MFC应用程序的对话框,在这个程序中,我创建了等待网络传输数据的线程,一旦该线程接收到数据,它就传送一个用户自定义的消息到对话框,使对话框知道有数据过来.但是为何在CMyDialog::PreTranslateMessage(MSG* pMsg)中能捕捉到WM_MYCMD这个消息,却不能和OnMyCommand相映射?

将你所有自定义消息的基类设为WM_APP,而不是WM_USER.


(18)在打开一个文档时退出?

我有一个mdi程序,在打开文件的处理过程中,我想判断该文档是不是应用程序需要处理的文档,因此,我检测文档中的某个数字是否符合要求,如何在发现不是该文档时出现一个错误提示,然后不打开该文档?

给文档设定某个标志,如果文档不是所要的就设定它.然后OnOpenDocument中检测,当发现标志被设定后返回FALSE.


(19)在CListCtrl控件中多选择项的删除?

如何从在CListCtrl中删除多个选择项?

按如下方法处理:如果你的在CListCtrl是m_list,to_delete是个整数数组.
i=3D0;
POSITION pos=3Dm_list.GetFirstSelectedItemPosition();
if(pos)
   while(pos)
    to_delete[i++]=3Dm_list.GetNextSelectedItem(pos);
然后用删除保存在to_delete中的项目,用GetSelectedCount来得到已选项的个数.



(20)工作线程的登录状态?

我使用循环删除了用AfxBeginThread创建的线程的好几个实例.每个线程打开一个iNET连接,打开一个URL并返回结果.我需要找出哪一个或者何时这些线程进入到登录状态.

按如下方法处理:(伪代码)

     // Start Threads
     for( unsigned u = 0; u < NUMBER_OF_THREADS; u++ )
{
     ThreadHandleArray[ u ] = AfxBeginThread( ...... )->m_hThread;
}

DWORD count = NUMBER_OF_THREADS
DWORD dwWait;

while( count )
{
     dwWait = ::WaitForMultipleObjects( count, ThreadHandleArray, FALSE,
INFINITE );

     if( dwWait >= WAIT_OBJECT_0 && dwWait < ( WAIT_OBJECT_0 + count ) )
     {
         dwWait -= WAIT_OBJECT_0;
         // dwWait now has index to thread that completed do whatever
you want to do with it
         // set array back up for next wait
         if( dwWait != ( count - 1 ) )
             ThreadHandleArray[ dwWait ] = ThreadHandleArray[
count - 1 ];
             count--;
     }
}

(21)如何增加视图中ActiveX控件的事件处理函数?

如果我在对话框中加入微软的网络浏览器,很容易通过类模板加入对事件的处理.但我现在在视图中用m_pBrowser=new CWebBrowser2加入了网络浏览器,我该如何对事件进行处理?

到www.vcdj.com(inet章节)去看看,有一篇文章名为"Building a Webbrowser in a Afternoon".如下的代码也可能是你所需要的:

#include // For AFX_EVENT def.

BOOL OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo)
{
     AFX_EVENT *pEvent = (AFX_EVENT *)pExtra;

     //If this is a control notification event.
     if (nCode == CN_EVENT)
     {
         // If we have information on this event.
         if (pEvent)
         {
             // Event DISPID is stored at pEvent->m_dispid
             // Event DISPPARAMS are stored at pEvent->m_pDispParams
             // Handle the event from here...
         }
     }

     return CWnd::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo);
}

(22)如何创建一个动态的Tree控件?

我想创建一个动态的tree控件,就象弹出窗口一样,但它并不象想象中那么容易.

方法一:用CreateWindow(SDK)创建风格为WS_POPUP,WS_CAPTION和WS_TICKFRAME的窗口,并作为父窗口.

方法二:创建一个包含Tree控件的对话框.


(23)SDI程序开始时不打开文档?

我创建了一个SDI应用,但每次启动时它都会打开一个文档("untitled"),如何不让它打开该文档呢?

看看InitInstance函数中有没有关于OnFileNew的调用,去掉它即可.


(24)List控件中整栏选择?

我在处理List控件时碰到了麻烦,我想创建一个ListView,来依据Tree控件的选择同时在ListView和ReportView中显示列表的信息.以下是相关的代码:

// Set full line select
ListView_SetExtendedListViewStyle(m_plstCustomers->GetSafeHwnd(),
LVS_EX_FULLROWSELECT);

按如下方法处理:

// -------------------- begin of snippet --------------------------------
bool CCommCtrlUtil32::ListCtrl_ModifyExtendedStyle(CListCtrl& p_rListCtrl,
                                    const DWORD p_dwStyleEx,
                                    const bool p_bAdd)
{
     HWND t_hWnd = p_rListCtrl.GetSafeHwnd();
     DWORD t_dwStyleEx = ListView_GetExtendedListViewStyle(t_hWnd);

     if(p_bAdd)
     {
         if(0 == (p_dwStyleEx & t_dwStyleEx))
         {
             // add style
             t_dwStyleEx |= p_dwStyleEx;
         }
     }
     else
     {
         if(0 != (p_dwStyleEx & t_dwStyleEx))
         {
             // remove style
             t_dwStyleEx &= ~p_dwStyleEx;
         }
     }

     ListView_SetExtendedListViewStyle(t_hWnd, t_dwStyleEx);

     return true;
}


(25)如何重载MRU文件?

我创建了一个应用程序可以载入图象文件,但当我点击FILE菜单下MRU文件列表时,却不能从磁盘载入以前曾经打开过的文件.

下面是我所能想到的解决方案:
(1)在文档类中定义一个成员函数(例如:CMyDoc::Reopen)来处理重新打开这个问题,指明参数和返回值.
(2)产生一个CMultiDocTemplate的继承类(如CMyDocTemplate),定义一个构造函数,取和基类相同的参数,不做任何事,只是调用基类的构造函数.
(3)重载MatchDocType:
CMyDocTemplate::Confidence CMyDocTemplate::MatchDocType(
     LPCTSTR lpszPath,
     CDocument *&rpDocMatch
     )
{
     Confidence match = CMultiDocTemplate::MatchDocType(lpszPath, rpDocMatch);

     if(yesAlreadyOpen == match) // clear enough
     {
         ASSERT_KINDOF(CMyDoc, rpDocMatch);
         ((CMyDoc *) rpDocMatch)->Reopen(/* your parameters */);

         // you can take any other actions here...
     }

     return match;
}
当这个函数返回"yesAlreadyOpen"时,你的文档框架将会被激活.

(26)CImageList控件中图象橙色被显示为黄色?

我使用了一个CImageList控件来装入位图,用于TREE控件,其它的色彩都很正常就是橙色被显示成为黄色.

你只能使用系统指定的20种颜色(橙色不包括在内);当然,你也可以用下面的方法来装载位图资源而不受颜色数的限制.

HBITMAP LoadResourceBitmap(HINSTANCE hInstance, LPSTR lpString,
                            HPALETTE FAR* lphPalette)
{
     HRSRC hRsrc;
     HGLOBAL hGlobal;
     HBITMAP hBitmapFinal = NULL;
     LPBITMAPINFOHEADER lpbi;
     HDC hdc;
     int iNumColors;
     if (hRsrc = ::FindResource(hInstance, lpString, RT_BITMAP))
{
   hGlobal = ::LoadResource(hInstance, hRsrc);
   lpbi = (LPBITMAPINFOHEADER)LockResource(hGlobal);
   hdc = ::GetDC(NULL);
   *lphPalette = CreateDIBPalette ((LPBITMAPINFO)lpbi, &iNumColors);
   if (*lphPalette)
   {
    ::SelectPalette(hdc,*lphPalette,FALSE);
    ::RealizePalette(hdc);
   }
   hBitmapFinal = ::CreateDIBitmap(hdc,
        (LPBITMAPINFOHEADER)lpbi,
        (LONG)CBM_INIT,
        (LPSTR)lpbi + lpbi->biSize + iNumColors * sizeof(RGBQUAD),
                    (LPBITMAPINFO)lpbi,
                    DIB_RGB_COLORS );
   ::ReleaseDC(NULL,hdc);
// ::UnlockResource(hGlobal);
// ::FreeResource(hGlobal);
}
     return (hBitmapFinal);
}

// internally used by LoadResourceBitmap
HPALETTE CreateDIBPalette (LPBITMAPINFO lpbmi, LPINT lpiNumColors)
{
LPBITMAPINFOHEADER lpbi;
LPLOGPALETTE lpPal;
HANDLE hLogPal;
HPALETTE hPal = NULL;
int i;
lpbi = (LPBITMAPINFOHEADER)lpbmi;
if (lpbi->biBitCount <= 8)
   *lpiNumColors = (1 << lpbi->biBitCount);
else
   *lpiNumColors = 0; // No palette needed for 24 BPP DIB
if (lpbi->biClrUsed > 0)
   *lpiNumColors = lpbi->biClrUsed; // Use biClrUsed
if (*lpiNumColors)
{
   hLogPal = GlobalAlloc (GHND, sizeof (LOGPALETTE) +
    sizeof (PALETTEENTRY) * (*lpiNumColors));
   lpPal = (LPLOGPALETTE) GlobalLock (hLogPal);
   lpPal->palVersion = 0x300;
   lpPal->palNumEntries = *lpiNumColors;
   for (i = 0; i < *lpiNumColors; i++)
   {
    lpPal->pal
PalEntry.
peRed = lpbmi->bmiColors.rgbRed;
    lpPal->palPalEntry.peGreen = lpbmi->bmiColors.rgbGreen;
    lpPal->palPalEntry.peBlue = lpbmi->bmiColors.rgbBlue;
    if (i<=10 || i>=246)
     lpPal->palPalEntry.peFlags = PC_NOCOLLAPSE;
    else
     lpPal->palPalEntry.peFlags = 0;
   }
   hPal = CreatePalette (lpPal);
   GlobalUnlock (hLogPal);
   GlobalFree (hLogPal);
}
return hPal;
}
该函数也重载了位图调色板,这个功能被CBitmap::LoadBitmap忽略了(它假定位图只使用20种颜色).因此要保证在DC中有SelectPalette和RealizePalette.

(27)无法正确改变应用程序的图标?

我有一个基于对话框的应用程序,在初始化时我使用了AfxGetApp()->LoadIcon(IDI_BRIEFCASE)来载入自己的图标,当把程序拷贝到桌面上时,图标是我所期望的.但在资源管理器中的图标却还是MFC的图标.

资源管理器仅使用16x16的小图标,可能你在资源编辑器中只修改了32x32的标准图标.你需要重建16x16的小图标.

(28)工具条状态的问题?

在应用程序中我创建了三个工具条,我想让它们在应用程序启动的时候排成一行正好在主菜单的下面,我该如何去做?

在VC CDs上有一个例子:

int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
//other stuff here...

     EnableDocking(CBRS_ALIGN_ANY);

     DockControlBar(&m_wndToolBar,AFX_IDW_DOCKBAR_TOP);
     DockControlBarLeftOf(&m_wndListToolBar,&m_wndToolBar);

     return 0;
}

void CMainFrame::DockControlBarLeftOf(CToolBar* Bar,CToolBar* LeftOf)
{
     CRect rect;
     DWORD dw;
     UINT n;

     // get MFC to adjust the dimensions of all docked ToolBars
     // so that GetWindowRect will be accurate
     RecalcLayout();
     LeftOf->GetWindowRect(&rect);
     rect.OffsetRect(1,0);
     dw=LeftOf->GetBarStyle();
     n = 0;
     n = (dw & CBRS_ALIGN_TOP) ? AFX_IDW_DOCKBAR_TOP :n;
     n = (dw & CBRS_ALIGN_BOTTOM && n==0) ? AFX_IDW_DOCKBAR_BOTTOM :n;
     n = (dw & CBRS_ALIGN_LEFT && n==0) ? AFX_IDW_DOCKBAR_LEFT :n;
     n = (dw & CBRS_ALIGN_RIGHT && n==0) ? AFX_IDW_DOCKBAR_RIGHT :n;

     // When we take the default parameters on rect, DockControlBar will dock
     // each Toolbar on a seperate line. By calculating a rectangle, we in effect
     // are simulating a Toolbar being dragged to that location and docked.
     DockControlBar(Bar,n,&rect);
}

(29)在SDI应用程序中使用Active控件?

我刚了解到如何在MFC应用程序中使用Active控件,文档上说只能在视图为CFormView和CDialog时使用,但要是其它的情况该怎么办呢?

你可以在你应用程序的任何地方使用Active控件,而不仅仅局限于CFormView和CDialog为视图基类的情况.DevStudio通过资源编辑器和对话框模板来使得在上述两个条件下使用Active控件更容易.因此,你也可以在任何视图中使用Active控件,条件是你直接操纵该控件,创建它并手工的布置好它的位置(这也是DevStudio为你所做的事).

(30)有RichEdit控件的对话框无法正常显示?

我在对话框中放置了一个RichEdit控件,但是对话框却无法正常显示.

在你的应用程序InitInstance()中调用了::AfxInitRichEdit()吗?

VC++ | 阅读 1826 次
文章评论,共0条
游客请输入验证码
浏览195173次