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 如何讓屬性頁具有兩行标簽?
A
從CPropertySheet派生一個自己的類,添加一個PreCreateWindow的處理,然後在調用基類的處理前加如下代碼:cs.style |= TCS_MULTILINE;
//-----------------------------------------------------------
Q 如何隐藏屬性頁的标題欄?
A
從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();