秀纳

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

这个Back健的处理很奇怪,如果默认不做任何处理,即使当前Dialog上存在一个Edit Control,它还是不会充当回退删除健的角色,还是会关闭当前对话框,回退到上一个。解决的办法也很简单 按Back健时,OS会抛出一个WM_HOTKEY的消息出来,我们可以捕获这个消息重写Back健的行为

代码如下:


在OnInitDialog时 发送SHCMBM_OVERRIDEKEY 重写VK_BACK的行为。

HWND hwndMenuBar = SHFindMenuBar(m_hWnd);
SendMessage(hwndMenuBar, SHCMBM_OVERRIDEKEY, VK_TBACK, MAKELPARAM(SHMBOF_NODEFAULT | SHMBOF_NOTIFY, SHMBOF_NODEFAULT | SHMBOF_NOTIFY));

然后在Dailog响应 WM_HOTKEY时进行如下处理:


LRESULT CMyDlg::OnHotKey(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
if(VK_TBACK == HIWORD(lParam))
{
bHandled = true;
SHSendBackToFocusWindow(uMsg, wParam, lParam);
}
return 0;

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

  1. 如果当前窗口不是一个DialogBox或是没有EditBox,当按下后退键时,应该显示上一个窗口。但是当前的窗口不应被销毁,而只是被前一个窗口覆盖。
  2. 如果当前窗口是一个MessageBox或者是一个没有EditBox的模态Dialog,当按下后退键时,应该关闭该对话框。对于MessageBox,对话框的返回值可能是 IDNO, IDCANCEL或IDOK;对于模态对话框,对话框会得到一个ID值为IDCANCEL的WM_COMMAND的消息。
  3. 如果当前的窗口含有EditBox,当按下后退键时,应该删除EditBox中的最后一个字符。

 对于第三种情况,系统并不会自动处理,需要我们自己做一点工作。

首先,我们需要向MenuBar发送一个SHCMBM_OVERRIDEKEY消息,来通知Menubar我们要改变后退键的行为。

SHCMBM_OVERRIDEKEY消息的wParam参数是要改变行为的键值,如下表所示:

Key Meaning
VK_TBACK Back button
VK_TSOFT1 Left SoftKeyBar button
VK_TSOFT2 Right SoftKeyBar button
VK_TVOLUMEUP Up volume button
VK_TVOLUMEDOWN Down volume button
VK_TRECORD Record button

 

 SHCMBM_OVERRIDEKEY消息的lParam参数是我们要改变的行为,其中lParam的低字节是掩码,高字节是值。

例如,我们要把后退键的缺省行为去掉,并希望当按下后退键时,会向当前窗口发送WM_HOTKEY的消息,那么,我们可以这么做:

SendMessage (SHFindMenuBar (hWnd), SHCMBM_OVERRIDEKEY, VK_TBACK, 
             MAKELPARAM (SHMBOF_NODEFAULT | SHMBOF_NOTIFY, 
                         SHMBOF_NODEFAULT | SHMBOF_NOTIFY));

SHMBOF_NODEFAULT是去掉后退键的缺省行为,SHMBOF_NOTIFY是要向窗口发送键按下的消息。

MAKELPARAM宏的第一个参数是低字,第二个参数是高字。

如果我们只是要去掉后退键的缺省行为,而不需要后退键向窗口发送WM_HOTKEY的消息,可以这么做:

SendMessage (SHFindMenuBar (hWnd), SHCMBM_OVERRIDEKEY, VK_TBACK,
             MAKELPARAM (SHMBOF_NODEFAULT | SHMBOF_NOTIFY,
                         SHMBOF_NODEFAULT));

如果要恢复后退键的缺省行为,可以这么做:

SendMessage (SHFindMenuBar (hWnd), SHCMBM_OVERRIDEKEY, VK_TBACK,
             MAKELPARAM (SHMBOF_NODEFAULT | SHMBOF_NOTIFY,
                         0));

 

窗口收到的WM_HOTKEY消息中,wParam表示按下的键,如下表所示:

Key Value
VK_TSOFT1 0
VK_TSOFT2 1
VK_TBACK 2
VK_TVOLUMEUP 3
VK_TVOLUMEDOWN 4
VK_TRECORD 5

 

lParam也含有按下键的值,但是有所区别。lParam中,高字表示按下的键值,低字则表示按下值的其他标志,对于Smartphone有用的是标志是MOD_KEYUP,表示键已经被释放了。

当我们收到WM_HOTKEY消息时,需要处理删除字符的操作,此时,不需要我们自己写代码完成,只需要调用系统提供的一个函数即可:

void SHSendBackToFocusWindow (UINT uMsg, WPARAM wp, LPARAM lp);

所以,我们处理WM_HOTKEY消息的代码可以这么写:

case WM_HOTKEY:
    if (HIWORD (lParam) == VK_TBACK)
        SHSendBackToFocusWindow (wMsg, wParam, lParam);
这样,就会删除最后的字符了。
最后一点,如果MenuBar被销毁,则改变后退键的行为会自动终止,不需要再写恢复代码。


BOOL InitWindow(
    
const HWND hDlg, 
    UINT nToolBarId
    )
{
    
// Specify that the dialog box should stretch full screen
    SHINITDLGINFO shidi;
    ZeroMemory(
&shidi, sizeof(shidi));
    shidi.dwMask 
= SHIDIM_FLAGS;
    shidi.dwFlags 
= SHIDIF_SIZEDLGFULLSCREEN;
    shidi.hDlg 
= hDlg;

    
// set up Soft Keys menu
    SHMENUBARINFO mbi;
    ZeroMemory(
&mbi, sizeof(SHMENUBARINFO));
    mbi.cbSize 
= sizeof(SHMENUBARINFO);
    mbi.hwndParent 
= hDlg;
    mbi.nToolBarId 
= nToolBarId;
    mbi.hInstRes 
= g_hInst;

    
// If we could not initialize the dialog box, return an error
    if (FALSE == (SHInitDialog(&shidi) && SHCreateMenuBar(&mbi)))
    
{
        
return FALSE;
    }


    
// set the title bar
    SetWindowText(hDlg, tszTitle);

    
// In order to make Back work properly, it's necessary to 
    
// override it and then call the appropriate SH API
    (void)SendMessage(mbi.hwndMB, SHCMBM_OVERRIDEKEY, VK_TBACK,
        MAKELPARAM(SHMBOF_NODEFAULT 
| SHMBOF_NOTIFY,
        SHMBOF_NODEFAULT 
| SHMBOF_NOTIFY));

    
return TRUE;
    }



//
//  FUNCTION: WndProc(HWND, unsigned, WORD, LONG)
//
//  PURPOSE:  Processes messages for the main window.
//

BOOL CALLBACK DlgProc (
    HWND hwnd, 
    UINT Msg, 
    WPARAM wParam, 
    LPARAM lParam)
{
    BOOL bReturn 
= TRUE;

    
switch(Msg)
    
{
    
case WM_INITDIALOG:

        
// Initialize the dialog and softkey menu
        if (FALSE == InitWindow(hwnd, IDR_BACK_MENUBAR))
        
{
            EndDialog(hwnd, 
-1);
        }

        
break;

    
case WM_COMMAND:

        
switch (wParam)
        
{
        
case IDOK:
            EndDialog(hwnd,IDOK);
            
break;
        
default:
            bReturn 
= FALSE;
        }

        
break;

    
case WM_HOTKEY:

        
// If back key is overriden, back button messages are sent in a WM_HOTKEY to the menu bar
        
// with the id VK_TBACK in the LPARAM.
        if (VK_TBACK == HIWORD(lParam) && (0 != (MOD_KEYUP & LOWORD(lParam))))
        
{
            
// Send a message to the check box to see if it's checked or not
            HWND hwndCheck = GetDlgItem(hwnd, IDC_CHECKBACK);

            
if (BST_CHECKED == SendMessage(hwndCheck, BM_GETCHECK, 00))
            
{
                
// check box is enabled, so we process the back key
                SHSendBackToFocusWindow(Msg, wParam, lParam);
            }

            
else
            
{
                
// not enabled, revert to default back behaviour
                MessageBox(hwnd, tszBackText, tszBackCaption, MB_OK | MB_ICONINFORMATION);
                SHNavigateBack();
            }

        }

        
break;

    
default:
        bReturn 
= FALSE;
        
break;

    }

    
return bReturn;
}
posted on 2007-08-10 20:09  秀纳  阅读(1984)  评论(0编辑  收藏  举报