如何处理Syslink控件的NM_CLICK

时间:2012-05-23 18:52:19

标签: c++ winapi visual-c++ native win32gui

做了相当多的研究试图弄清楚如何让它正常工作。我读过如果你过滤WM_NOTIFY - > NM_CLICK,它会捕获syslink的实际click事件。麻烦的是它抓住了这个事件,虽然它被卡在无休止的递归中,几秒钟内你就有了数百个浏览器窗口或者没有链接打开了。

采取的措施

  1. 在对话框
  2. 上创建Syslink
  3. 将标题添加到Syslink控制链接并将IDD更改为IDC_LINK1
  4. 为NM_CLICK事件过滤WM_NOTIFY

       case WM_NOTIFY:
      //case NM_CLICK:
      switch(LOWORD(wParam))
      {
          case NM_CLICK:
             switch(LOWORD(wParam))
         {
                 case IDC_LINK1:
                     // Standard ShellExecute with added check for IsLinkCtrl to make sure its the right kind of control.
                     OpenLink(hWndDlg, LOWORD(wParam));            
             break;
         }
         break;
      }
      break;
    
  5. 我想我真正的问题是我该如何正确地做到这一点?我没有看到任何好的示例显示如何正确过滤Syslink以将链接作为URL执行。

3 个答案:

答案 0 :(得分:3)

为了澄清,我不认为您使用的是托管C ++,因为我不确定您为什么将NM_CLICK通知代码称为事件。 此外,您不必捕获任何内容,您不处理任何异常,您只是处理WM_NOTIFY消息。

无论如何,我不确定为什么你会遇到这种特殊的行为,因为我没有看到你在代码片段之外做了什么,但我知道是什么导致了它。 在我们的代码段中,您使用wParam来确定通知代码,这是不正确的。此控件不使用wParam。要确定通知代码,您应该执行以下操作:

    NMHDR* pHeader = (NMHDR*)lParam;

    switch (pHeader->code)

pHeader->代码包含您应使用的通知代码值, pHeader-> hwndFrom 是所单击控件的句柄。

此外,您再次使用LOWORD(wParam)并将其作为参数传递给函数调用。您没有显示您在此函数中执行的操作,但我可以断定代码也不正确。 相同的lParam是指向NMLINK结构的指针。 该结构的第一个成员在NMHDR上面提到,下一个成员是LITEM结构,应该用来确定URL是什么。

    NMLINK* pNMLink = (NMLINK*)lParam;
    LITEM iItem = pNMLink->item;

item.szUrl 是您在调用ShellExecute调用open时应使用的URL。

答案 1 :(得分:2)

我发现了一种成功的方法,可以在不进行递归的情况下使其工作。消息循环似乎在连续循环中继续读取,如果不使用正确的结构进行过滤,它将陷入无限递归。这适合我。如果你有更好的输入请做插件。

采取正确的步骤。

  1. 创建WM_NOTIFY消息过滤器事件。
  2. 使用NMHDR创建Switch语句以解析NM_CLICK的代码。
  3. 检查wParam以确定单击的正确控件。
  4. 使用ShellExecute执行链接。
  5. 使用了以下代码。

           case WM_NOTIFY:
               //NMHDR* pHeader = (NMHDR*)lParam;
               //NMLINK* pNMLink = (NMLINK*)lParam;
               //LITEM iItem = pNMLink->item;
               switch(((NMHDR *)lParam)->code)
               {
                   case NM_CLICK:
                   { // Included to avoid "case" skip statements.
                       times++;
    
                       NMLINK* pNMLink = (NMLINK*)lParam;
                       LITEM iItem = pNMLink->item;
                       // Custom OutputDebugString
                       winapi::Output("NM_CLICK: Fired %d time%s!\n", times, (times <= 1) ? L"" : L"s");
    #ifdef DEBUG
                       assert(iItem.szID);
                       MessageBox(NULL, (LPCWSTR)lParam, L"Assert", MB_OK|MB_ICONINFORMATION);
    #endif
                       if(wParam == IDC_LINK1)
                       {
                           winapi::Output("Success!");
                           OpenLink(hWndDlg, LOWORD(wParam));
                       }
    

    注意:如果您依赖包含HTML属性的链接(链接或此处)来提供Shellexecute其网址路径,请使用NMLINK结构。

答案 2 :(得分:1)

无论

  1. 您的OpenLink功能导致发送另一条消息(最有可能),或

  2. 这不是调用OpenLink的唯一代码,或

  3. 您的代码不是来自WM_NOTIFY,而是来自上述案例,或

  4. 即使您已经处理过该消息,也请致电DefWindowProc

  5. 尝试

      break; // make sure there's no fall-through here
      case NM_CLICK:
         switch(LOWORD(wParam))
         {
             case IDC_LINK1:
                 // Standard ShellExecute with added check for IsLinkCtrl to make sure its the right kind of control.
                 OpenLink(hWndDlg, LOWORD(wParam));            
                 return TRUE; // handled, don't pass to DefWindowProc
         }
         break;