1. 程式人生 > >VC回車鍵的使用 Edit內回車

VC回車鍵的使用 Edit內回車

http://www.cnblogs.com/joinclear/archive/2010/11/18/1881251.html

在VC中建立一基於對話方塊的工程,編譯執行,成功。面對著剛剛建立的工程,心裡那個高興呀。突然一時心血來潮,按了個回車鍵,工程一閃而過沒了。再編譯執行,成功。按了個ESC鍵,工程一閃而過也沒了。
為什麼會這樣,因為CDialog 中有預設對ENTER和ESC鍵的處理。
解決這種一按回車和ESC鍵就關閉工程的正確處理方法是:觸發PreTranslateMessage訊息,截獲ENTER和ESC對對話方塊的訊息。
程式碼如下:

複製程式碼 程式碼 BOOL CXXX::PreTranslateMessage(MSG
* pMsg) { if(pMsg->message == WM_KEYDOWN) { switch(pMsg->wParam) { case VK_RETURN://遮蔽回車鍵return TRUE; case VK_ESCAPE://遮蔽ESC鍵return TRUE; } } return CDialog::PreTranslateMessage(pMsg); } 複製程式碼

OK了,這下好了。突然我在對話方塊上加了一個編輯框和一個列表框,我想先在編輯框中輸入內容,然後按一下回車鍵,就把編輯框的內容插入到列表框中。

突然一想還真無從下手,再一想還是在PreTranslateMessage裡面做,上面的我是直接return TRUE;的。我在這個return TRUE;上面做就行了。

程式碼如下:

複製程式碼 程式碼 BOOL CXXX::PreTranslateMessage(MSG* pMsg) { HWND h1 = ::GetDlgItem(m_hWnd,IDC_EDIT1); if(pMsg->message == WM_KEYDOWN) { switch(pMsg->wParam) {
case VK_RETURN: UpdateData(); if (pMsg->hwnd == h1) { m_list.AddString(m_edit1); } return TRUE; case VK_ESCAPE: return TRUE; break; } } return CDialog::PreTranslateMessage(pMsg); } 複製程式碼


要是兩個編輯框呢。在編輯框1中回車,把編輯框1的內容加到列表框,在編輯框2中回車,把編輯框2的內容加到列表框,於是這樣。

程式碼如下:

複製程式碼 程式碼 BOOL CXXX::PreTranslateMessage(MSG* pMsg) { HWND h1 = ::GetDlgItem(m_hWnd,IDC_EDIT1); HWND h2 = ::GetDlgItem(m_hWnd,IDC_EDIT2); if(pMsg->message == WM_KEYDOWN) { switch(pMsg->wParam) { case VK_RETURN: UpdateData(); if (pMsg->hwnd == h1) { m_list.AddString(m_edit1); } if (pMsg->hwnd == h2) { m_list.AddString(m_edit2); } return TRUE; case VK_ESCAPE: return TRUE; break; } } return CDialog::PreTranslateMessage(pMsg); } 複製程式碼


為了下面的使用,先來講講VC的視窗類和視窗控制代碼的轉換。
視窗類就是CWnd,視窗控制代碼就是HWND。CWnd和HWND之間互相轉換程式碼如下:
   

CWnd *pWnd; HWND hWnd; hWnd = pWnd->GetSafeHwnd(); //CWnd->HWND pWnd = CWnd::FromHandle(hWnd); //HWND->CWnd

則這樣上面的兩個編輯框的程式碼,改一下第二個編輯框先得到CWnd,轉一下然後和HWnd比較。
改了的程式碼如下:

複製程式碼 程式碼 BOOL CXXX::PreTranslateMessage(MSG* pMsg) { HWND h1 = ::GetDlgItem(m_hWnd,IDC_EDIT1); CWnd *h2=GetDlgItem(IDC_EDIT2); if(pMsg->message == WM_KEYDOWN) { switch(pMsg->wParam) { case VK_RETURN: UpdateData(); if (pMsg->hwnd == h1) { m_list.AddString(m_edit1); } if (pMsg->hwnd == h2->GetSafeHwnd()) { m_list.AddString(m_edit2); } return TRUE; case VK_ESCAPE: return TRUE; break; } } return CDialog::PreTranslateMessage(pMsg); } 複製程式碼

完成了,功能一模一樣。
好開心!
舉一反三,下面別的控制元件你也可以這樣做了。如:列表框
等等。

突然一天,我發現這種做法失效了。失效在組合框上了。
原本的希望卻變成了失望。痛苦啊。
程式如下:

複製程式碼 程式碼 BOOL CXXX::PreTranslateMessage(MSG* pMsg) { HWND h3 = ::GetDlgItem(m_hWnd,IDC_COMBO1); if(pMsg->message == WM_KEYDOWN) { switch(pMsg->wParam) { case VK_RETURN: UpdateData(); if (pMsg->hwnd == h3) { m_list.AddString(m_combo1); } return TRUE; case VK_ESCAPE: return TRUE; break; } } return CDialog::PreTranslateMessage(pMsg); } 複製程式碼

於是用SPY++一看,組合框卻有兩個控制代碼,一個是ComboBox,還有一個是Edit的控制代碼。想想也是呀:組合框的可視部分就是由一個Edit組合成的,而pMsg->hwnd得到的控制代碼就是這個Edit所指的控制代碼(因為回車就是在這個Edit裡面敲的),而HWND h3 =::GetDlgItem(m_hWnd,IDC_COMBO1);得到的這個控制代碼卻是ComboBox的控制代碼,pMsg->hwnd 和 h3這兩個當然不等了。
呵呵,找到了原因就好辦了。

這下記起來有個這個函數了吧:CWnd* GetParent() const;
其實ComboBox就是Edit的父視窗(組合框和編輯框都可以看成是視窗)。
哦,既然pMsg->hwnd是Edit的控制代碼,ComboBox又是Edit的父視窗,那用個GetParent();就得到父視窗的控制代碼了,就可以和得到的控制代碼比較了。
大功告成,於是程式碼就出來了。

程式碼如下(舉了兩個組合框):

複製程式碼 程式碼 BOOL CEntercomboDlg::PreTranslateMessage(MSG* pMsg) { CWnd *h1=GetDlgItem(IDC_COMBO1); CWnd *h2=GetDlgItem(IDC_COMBO2); CWnd* hh = CWnd::FromHandle(pMsg->hwnd); CWnd* hhp = NULL; if(pMsg->message == WM_KEYDOWN) { switch(pMsg->wParam) { case VK_RETURN: UpdateData(); hhp = hh->GetParent(); if (hhp == h1) { m_list.AddString(m_combo1); } if (hhp == h2) { m_list.AddString(m_combo2); } return TRUE; case VK_ESCAPE: return TRUE; break; } } return CDialog::PreTranslateMessage(pMsg); } 複製程式碼