关于长按触摸笔[转]

来源:互联网 发布:字符串的拆分JS 编辑:程序博客网 时间:2024/05/04 00:15

Pocket PC Developer Network / Articles /
All about context menus
By Nicholas Tsipanov, September 18, 2002.
Print version

Introduction
Context menu is a very important element of Pocket PC user interface but unfortunatelly this feature is not described enough in helps. This articles explains using context menu in eVC++ applications and gives step-by-step instructions.

What You Need

Microsoft ebedded Visual C++ version 3.0
ContextMenu.zip sample (13 Kb)

Preface
How can I use context menu in my dialog or view in MFC based application? Before answering this question I would like to point to the article on Microsoft.com concerning this question, but from my point of view this article is too short and lacks some examples. Here we will tell this story in other words.

To use the context menus in your application create your own control descendant from the control to use. There is a well-known bug in controls behaviour when you use it in other way than creating from template using the design editor. This bug is discussed in article about demonstration of it in CButton class descendants and here we will use similar technique for CListControl.

Creating own class is simple and straightforward:

class CMyListCtrl : public CListCtrl
{
......
// Implementation
      //{{AFX_MSG(CMyListCtrl)
      afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
      //}}AFX_MSG
.....
};


This is the method to have correct stylus click handling.

void CMyListCtrl::OnLButtonDown(UINT nFlags, CPoint point)
{

//The code below fixes wrong MFC behaviour on Pocket PC 2002 devices
//(running circles appears twice while you tap and hold

 Default();
}


At this point you should decide where you want to handle the context menu notification: either the control itself or in its window parent. Both approaches are possible: if you create control that has common menu (i.e. edit control) you could create and track menu in the control's code. Otherwise it could be more convinient to handle this notification in its parent. In both cases you have to add the method OnContextMenu to your handling class:


class CMyListCtrl : public CListCtrl
{
......
// Implementation
 //{{AFX_MSG(CMyListCtrl)
 afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
 //}}AFX_MSG
 afx_msg BOOL OnContextMenu(NMHDR *pNotifyStruct, LRESULT *result);
.....
};

BOOL CMyListCtrl::OnContextMenu(NMHDR *pNotifyStruct, LRESULT *result)
{
//GN_CONTEXTMENU sends NMRGINFO structure through notify struct parameter
 PNMRGINFO pInfo=(PNMRGINFO)pNotifyStruct;

 CMenu Menu;
 Menu.LoadMenu(IDR_MENUBAR_MYCONTROL);
 Menu.GetSubMenu(0)->TrackPopupMenu( TPM_LEFTALIGN, pInfo->ptAction.x, pInfo->ptAction.y, this);

 *result = TRUE; //This is important!
 return TRUE;
}


In this code we have loaded the context menu from the resources. You have to create a menu bar containing one submenu, which will be shown in control.

If you'd like to have menu created on the fly then use the following code to create a menu:

CMenu Menu;
Menu.CreatePopupMenu();
Menu.AppendMenu(MF_ENABLED,IDR_MENUBAR_MYCONTROL_CUT, _T("Cut"));
Menu.AppendMenu(MF_ENABLED,IDR_MENUBAR_MYCONTROL_COPY, _T("Copy"));
Menu.AppendMenu(MF_ENABLED,IDR_MENUBAR_MYCONTROL_PASTE, _T("Paste"));
Menu.AppendMenu(MF_ENABLED,IDR_MENUBAR_MYCONTROL_WHATEVER, _T("Whatever"));
Menu.TrackPopupMenu( TPM_LEFTALIGN, pInfo->ptAction.x, pInfo->ptAction.y, GetParent());


Ensure that you defined IDR_* constants since Visual Studio won't do it for you in this case (but you can use already defined IDs)

Now you can compile the code to see if it works. But it won't, though compiled without errors. What happened? We forget to add the notification handler in the message map: If we add OnContextMenu to control itself our message map will be look like this:

BEGIN_MESSAGE_MAP(CMyListCtrl, CListCtrl)
 //{{AFX_MSG_MAP(CMyListCtrl)
 ON_NOTIFY_REFLECT(GN_CONTEXTMENU, OnContextMenu)
 ON_WM_LBUTTONDOWN()
 ... // some other entries
 //}}AFX_MSG_MAP
END_MESSAGE_MAP()


And if you add it to the parent (I mean window parent here, not C++) notification add in this way:

BEGIN_MESSAGE_MAP(CMyDialog, CListCtrl)
 //{{AFX_MSG_MAP(CMyListCtrl)
 ON_NOTIFY(GN_CONTEXTMENU, OnContextMenu)
 ... // some other entries
 //}}AFX_MSG_MAP
END_MESSAGE_MAP()


Note that we use ON_NOTIFY instead of ON_NOTIFY_REFLECT macro.

Now its time to handle thse menu entries we added. In simplest case (keep it simple, eh?) - when there are few menu static entries we provide ON_COMMAND handler for each menu entry:

BEGIN_MESSAGE_MAP(CMyDialog, CListCtrl)
 //{{AFX_MSG_MAP(CMyListCtrl)
 ON_NOTIFY(GN_CONTEXTMENU, OnContextMenu)
 ON_COMMAND(IDR_MENUBAR_MYCONTROL_CUT, OnMyControlCut)
 ON_COMMAND(IDR_MENUBAR_MYCONTROL_COPY, OnMyControlCopy)
 ON_COMMAND(IDR_MENUBAR_MYCONTROL_PASTE, OnMyControlPaste)
 ... // some other entries
 //}}AFX_MSG_MAP
END_MESSAGE_MAP()


And the handlers have the simple signature:

void CMyDialog::OnMyControlCut()
{
 // Cut, cut, cut!!
}


If you have dynamic menus or want to have one handler for a range of menu items use ON_COMMAND_RANGE macro:

BEGIN_MESSAGE_MAP(CMyDialog, CListCtrl)
 //{{AFX_MSG_MAP(CMyListCtrl)
 ON_NOTIFY(GN_CONTEXTMENU, OnContextMenu)
 ON_COMMAND_RANGE(IDR_MENUBAR_MYCONTROL_MIN, IDR_MENUBAR_MYCONTROL_MAX, OnMyControlMenu)
 ... // some other entries
 //}}AFX_MSG_MAP
END_MESSAGE_MAP()


In this case handler receives actual command menu item ID.

void CMyDialog::OnMyControlMenu(UINT idCmd)
{
 UINT nIndex = idCmd - IDR_MENUBAR_MYCONTROL_MIN;
 swich(nIndex)
 {
  ....
 }
}


Here we used list control for example but you can this approach will work for other controls as well, such as CListBox.

Sample
If you want the illustrations in compilable form please download the sample project - ContextMenu.zip (13 Kb).

Discuss
Discuss this article. Here you can write your comments and read comments of other developers.
Rate this article:     Poor       Excellent     
  1 2 3 4 5  

注:简而言之,如果要在一个窗口中处理长按时间,通用的做法是在WM_LBUTTONDOWN中使用SHRecognizeGesture判断,当然传入的标志位中须指明,长按后立即返回- SHRG_RETURNCMD,至于SHRG_NOANIMATION则是取消长按产生的圆圈动画

For example:

SHRGINFO    shrg;
    
    shrg.cbSize = sizeof(shrg);
    shrg.hwndClient = hWnd;
    shrg.ptDown.x = LOWORD(lParam);
    shrg.ptDown.y = HIWORD(lParam);
    shrg.dwFlags = SHRG_RETURNCMD|SHRG_NOANIMATION;
    
    if (SHRecognizeGesture(&shrg) == GN_CONTEXTMENU)
    {

}

原创粉丝点击