天天看點

MFC基本操作

Q 如何處理ComboBox中的Enter鍵?避免退出程式?

A 在一般的EDIT中采用的方法是處理PretranlateMessage(),執行代碼

CWnd *pWnd = GetFocus();

if(pWnd != NULL)

{

  if(pWnd == GetDlgItem(IDC_EDIT1)

  {

     ...//IDC_EDIT1具有焦點

  }

}

但在ComboBox中好象不同,是ComboBox的編輯控件得到了焦點,是以判斷代碼:

BOOL CDlg::PreTranslateMessage(MSG *pMsg)

{

   if(pMsg->message==WM_KEYDOWN && pMsg->wParam == VK_RETURN)

   {

      CWnd *pWnd = GetFocus();

      if(pWnd != NULL)

      {

         if(pWnd->GetParent() == GetDlgItem(IDC_COMBO1)//更改ID

         {

               return TRUE;

         }

      }

   }

   return CDialog::PreTranslateMessage(pMsg);

}

//-------------------------------------------------

Q 動态建立的組合框如何設定下拉清單框的高度?

A m_combo.Create(WS_CHILD | WS_VISIBLE | WS_VSCROLL CBC_SORT | CBC_DROPDOWNLIST | WS_TABSTOP, CRect(320,10,580,280),this,114);

//CRect的最後一個參數(這裡是280)就表示下拉大小

//-------------------------------------------------

Q 是否能不選擇下拉清單樣式而禁止使用者輸入值,有什麼方法可以實作?

A 将下拉清單的編輯控件設定為隻讀的,方法如下:

CComboBox *pcombo;

CWnd *pWnd = pcombo->GetWindow(GW_CHILD);

while(pWnd)

{

  char classname[256];

  ::GetClassName(pWnd->m_hWnd,classname,256)

  if(strcmp(classname,"edit") == 0)

  {

     CEdit *pEdit;

     pEdit = new CEdit();

     pEdit->SubClassWindow(pWnd->m_hWnd);

     pEdit->SetReadOnly();

     pWnd = pWnd->GetNextWindow();

     delete pEdit;

  }

  if(pWnd)

     pWnd = pWnd->GetNextWindow();

}

//-------------------------------------------------

Q ComboBox的自定義彈出菜單,想在右擊組合框的編輯部分的時候彈出菜單?

A 一種方法就是在CCustomCombo的OnCtlColor函數裡進行,生成ComboBox中編輯框的子類,示例:

HBRUSH CCustomCombo::OnCtlColor(CDC *pDC,CWnd *pWnd,UINT nCtlColor)

{

  if(nCtlColor == CTLCOLOR_EDIT)

  {

     if(m_edit.GetSafeHwnd()==NULL)

        m_eidt.SubClassWindow(pWnd->GetSafeHwnd());

  }

  HBRUSH hbr = CComboBox::OnCtlColor(pDC,pWnd,nCtlColor);

  return hbr;

}

//其中m_edit是CEdit類的實作,它在WM_RBUTTONUP上顯示右鍵菜單

//-------------------------------------------------

Q 如何給按鈕加位圖

A

對動态建立的按鈕:

CButton button;

button.Create(_T("My Button"),WS_CHILD | WS_VISIBLE | BS_BITMAP,CRect(10,10,60,50),pParentWnd,1);

button.SetBitmap(::LoadBitmap(NULL,MAKEINTRESOURCE(IBM_CHECK)));

或者修改風格:

UINT Style = Button.GetButtonStyle();

Style = Style | BS_BITMAP;

Button.SetBitmap(::LoadBitmap(NULL,MAKEINTRESOURCE(IBM_CHECK)));

//-------------------------------------------------

Q 如何在CButton派生類中以及父對話框中捕獲BN_CLICKED消息?

A 于WM_NOTIFY消息相反,通知消息BN_CLICKED作為WM_COMMAND消息發送。是以應用程式應該使用ON_CONTROL_REFLECT_EC而不是ON_NOTIFY_REFLECT

//-------------------------------------------------

Q 如何判斷某個對象是否具有目前焦點?

A return (CWnd::GetFocus() == pWnd);

//-------------------------------------------------

Q 如何設定編輯控件的數字限制屬性?

A

long Style = GetWindowLong(m_EditCtrl.m_hWnd,GWL_STYLE);

Style |= ES_NUMBER;

SetWindowLong(m_EditCtrl.m_hWnd,GWL_STYLE,Style);

//-------------------------------------------------

Q 希望在LISTCTRL中顯示檔案,如何才能得到explorer使用的相同圖象?

A 可以将系統的ImageList加到LISTCTRL上,然後用具有SHGFI_ICON标志的SHGetFileInfo擷取适當的圖示索引:

//圖象清單設定

HIMAGELIST himagelist;

SHFILEINFO fi;

CImageList m_smalllist;

//得到系統小圖示清單的句柄

himagelist = (HIMAGELIST)SHGetFileInfo((LPCTSTR)_T("C://"),0,&fi,sizeof(SHFILEINFO),SHGFI_SYSICONINDEX | SHGFI_SMALLICON);

//添加到小圖象清單

m_smalllist.Attach(himagelist);

//設定LISTCTRL的圖象清單

m_listCtrl.SetImageList(&m_smalllist,LVSIL_SMALL);

//分離圖象清單

m_smalllist.Detach();

//-------------------------------------------------

Q 如何在清單的任何一列顯示圖示,而不是第一列?

A

LV_ITEM item;

...

item.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_STATE | LVIF_PARAM;

item.iItem = ...//設定行号

item.lParam = ...//如何需要就設定lparam參數

item.iSubItem = ...//設定列号,從0開始的

item.stateMask = LVIS_STATEIMAGEMASK;

item.state = INDEXTOSTATEIMAGEMASK(...);//參數為圖示号

item.iImage = ...//設定圖示号

item.pszText = ...//顯示文本

//插入新項

m_listctrl.InsertItem(&item);

//現在設定圖示

m_listctrl.SetItemText(0,4,szField);

//-------------------------------------------------

Q 給LISTBOX添加新項時如何實作自動下滾?

A 在調用AddString後,添加如下代碼:

m_listbox.SetTopIndex(m_listbox.GetCount()-1);

//-------------------------------------------------

Q listBox的文本超過框的寬度時,如何讓水準滾動條正常工作?

A 用下面的代碼,設定滾動條的寬度為最長的字元串寬度

void SetHorizontalExtent(CListBox &listbox)

{

    int index = listbox.GetCount();

    if(index == LB_ERROR)

       return;

    int nExtent = 0;

    if(index)

    {

        CDC *pDC = listbox.GetDC();

 CFont *poldfont = pDC->SelectObject(listbox.GetFont());

 CString s;

 SIZE text;

 LONG maxtxt = 0;

 whilw(index--)

 {

             listbox.GetText(index,s);

      text = pDC->GetOutputTextExtent(s);

      if(text.cx > maxtxt)

                 maxtxt = text.cx;

  }

        text.cx = maxtxt;

      pDC->LPToDP(&text);

      nExtent = text.cx+2;

      pDC->SelectObject(poldfont);

      listbox.ReleaseDC(pDC);

    }  

    listbox.SetHorizontalExtent(nExtent);

}

//-------------------------------------------------

Q 在拆分視圖的時候,建立了四個視圖(2行2列),右下的是CFormView,其他的都是CView,在CMainFrame的OnCreateCilent不管怎麼指定CRect的大小,下方的兩個視圖都占了整個視窗,需要拖動!

A 一般隻需要在OnCreateClient的末尾添加:

m_wndSpitter.SetRowInfo(0,200,0);//添加此行代碼

//-------------------------------------------------

Q 如何指定拆分視窗的最小寬度?

A 使用CSpitterWnd::SetColumnInfo()

  void SetColumnInfo(int col, //指定列

       int deal, //理想寬度(像素)

       int cxmin); //最小寬度(像素)

 在使用SetColumnInfo之後還應該調用RecalLayout();重新調整布局。

//--------------------------------------------------

Q 如何判斷工具欄是水準還是垂直的?

A if((m_toolbar.GetBarStyle() & CBRS_ALIGN_LEFT) == CBRS_ALIGN_LEFT ||

(m_toolbar.GetBarStyle() & CBRS_ALIGN_RIGHT) == CBRS_ALIGN_RIGHT)

     AfxMessageBox("vertical");

  else

     AfxMessageBox("horizontal");

//--------------------------------------------------

Q 程式設計方式修改工具欄按鈕的可見性?

A 示例代碼:

DWORD style = m_toolbar.GetButtonStyle(nIndex);

if(m_bHide)

   m_toolbar.SetButtonStyle(nIndex,style & ~WS_VISIBLE);

else

   m_toolbar.SetButtonStyle(nIndex,style | WS_VISIBLE);

m_bHide = !m_bHide;

//--------------------------------------------------

Q 如何在狀态欄添加按鈕并響應?

A 建立一個從CButton派生的CMyButton類,在主架構類添加CMyButton類的成員變量,然後在OnCreate函數中建立按鈕,并把它和狀态欄關聯起來:

m_mybtn.Create("MyButton",WS_CHILD | VISIBLE,CRect(0,0,60,20),&m_WndStatusBar,0);

通過處理BN_CLICKED消息,可以在CMyButton類中處理所有的點選事件

//--------------------------------------------------

Q 如何隐藏屬性CPropertySheet的标題欄,使用ModifyStyle(WINDOW_CAPTION,0)沒有效果

A 建立自己的CPropertySheet派生類,并覆寫OnInitDialog,轉到預設的情況後,使用ModifyStyle來删除WS_CAPTION标志

//--------------------------------------------------

Q 如何讓屬性頁有兩行标簽?

A 從CPropertySheet派生類,添加PreCreateWindow的處理,在調用基類之前添加代碼:

 cs.style |= TCS_MULTILINE;

//------------------------------------------------------

Q 如何在屬性表的兩個頁之間傳遞資料?

A

CPropertyPage有一個成員函數QuerySiblings(WPARAM, LPARAM)。應用程式可以使用這個函數。

QuerySiblings生成一條PSM_QUERYSIBLINGS消息,它傳遞給所有的兄弟,也就是屬性表上的其他屬性頁。   一般可建立一個所有頁可見的枚舉,如:

 enum{QUERY_MY_STRING,  QUERY_SOMETHING_ELSE,.......}

然後,在一個屬性頁需要其他屬性頁中的資訊時,使用代碼:

CString myString;

if(lL == QuerySiblings(QUERY_MY_STRING,(LPARAM)&myString))

{

         ....//擷取字元串

}

提供字元串的頁處理PSM_QUERYSIBLINGS消息:

LRESULT CPageThatHasString::OnQuerySiblings(WPARAM wParam, LPARAM lParam)

{

        if(QUERY_MY_STRING == wParam)

       {

              *((CString *)lParam) = _T(“Test String“);

               return 1L;

       }

       else

              return 0L;

}

//----------------------------------------------------------

Q  如何讓屬性頁具有兩行标簽?

從CPropertySheet派生一個自己的類,添加一個PreCreateWindow的處理,然後在調用基類的處理前加如下代碼:cs.style |= TCS_MULTILINE;

//-----------------------------------------------------------

Q  如何隐藏屬性頁的标題欄?

從CPropertySheet派生一個自己的類,并覆寫OnInitDialog,在轉到預設的情況以後,使用 ModifyStyle來删除标題欄标志WS_CAPTION。

   ModifyStyle(WS_CAPTION,0);

//-------------------------------------------------------------------

Q 如何枚舉桌面項目?

A

1 得到指向IShellFolder接口的指針

2 得到指向IMalloc接口的指針

3 得到指向IEnumIDList接口的指針

4 提取枚舉中下一項目的PIDL

5 測定PIDL代表的标志符的類型

6 處理該項目

7 釋放PIDL配置設定的記憶體

8 重複4到7步,知道所有的項目都枚舉完

9 釋放IShellFolder IMalloc IEnumIDList接口的指針

LPSHELLFOLDER lpshellfolder;

LPMALLOC lpmalloc;

LPENUMIDLIST lpidlist;

m_namecount = 0;

HRESULT hr = SHGetDestopFolder(&lpshellfolder);

if(hr == NOERROR)

{

    hr = ::SHGetMalloc(&lpmalloc);

    if(hr == NOERROR)

    {

        hr = lpshellfolder->EnumObject(NULL,SHCONTF_FOLDERS | SHCONTF_NONFOLDERS,&lpidlist);

        if(hr == NOERROR)

             ProcessFolder(lpshellfolder,lpmalloc,lpidlist);//custom deal function

        lpmalloc->Release();

        lpidlist->Release();

        InValidate();

    }

    lpshellfolder->Release();

}

void ***::ProcessFolder(LPSHELLFOLDER lpshellfolder,LPMALLOC lpmalloc,LPENUMIDLIST lpidlist)

{

   STRRET strret;

   ULONG numfetch;

   LPITEMIDLIST lpitemlist;

   HRESULT hr = lpidlist->Next(1,&lpitemlist,&numfetch);

   while(hr == NOERROR)

   {

       ULONG attributes = SFGAO_FOLDER;

       lpshellfolder->GetAttributes(1,(const struct _ITEMIDLIST **)&lpitemlist,&attributes);

       if(attributes & SFGAO_FOLDER)

       {

           hr = lpshellfolder->GetDiaplayNameOf(lpitemlist,SHGDN_NORMAL,&strret);

           if(m_nameCount < 20)

               m_names[m_namecount++] = strret.str;

       }

       lpmalloc->Free(lpitemlist);

       hr = lpidlist->Next(1,&lpitemlist,&numfetch);

   }

}

//-------------------------------------------------------------------

Q  如何建立桌面快捷方式?

A:

1 initialize com

2 create LShellLink Object

3 Use IShellLink interface to get the pointer about IPersistFile

4 Use IShellLink interface to initialize link

5 Use LPersistFile interface to save the link

6 Release all the com pointer

7 Com return to previous status

1

HRESULT hr = CoInitialize(NULL);

if(hr == S_OK)

{

  ...//Continue

}

2

IShellLink *pshelllink;

pshelllink = CoCreateInstance(CLSID_ShellLink,NULL,CLSCTX_INPROC_SERVER,IID_IShellLink,(void **)&pshelllink);

3

IPersistFile *persistfile;

persistfile = pshelllink->QueryInterface(IID_IPersistFile,(void **)&persistfile);

4

pshelllink->SetPath("C://config.sys");

pshelllink->SetDescription("ShortCut to config.sys");

5

char path[MAX_PATH];

GetWindowsDirectory(path,MAX_PATH);

int len = strlen(path);

strcpy(&path[len],"//desktop//config.lik");

//change the char from ANSI to UNICODE

OLECHAR widepath[MAX_PATH];

MultiByteToWideChar(CP_ACP,0,path,-1,widepath,MAX_PATH);

persistfile->Save(widepath,TRUE);

6

pshelllink->Release();

psersistfile->Release();

7

CoUnInitialize();