2

做了很多研究,试图弄清楚如何让它正常工作。我读到如果您过滤 WM_NOTIFY -> NM_CLICK,它将捕获系统链接的实际单击事件。麻烦的是它捕捉到了事件,尽管它陷入了无休止的递归中,并且在几秒钟内你就有了数百个浏览器窗口,或者链接打开了。

采取的步骤

  1. 在对话框中创建 Syslink
  2. 为Syslink控制链接添加标题并将IDD更改为IDC_LINK1
  3. 过滤 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;
    

我想我真正的问题是我该如何正确地做到这一点?我没有看到任何很好的例子来说明如何正确过滤 Syslink 以将链接作为 url 执行。

4

3 回答 3

3

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

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

    NMHDR* pHeader = (NMHDR*)lParam;

    switch (pHeader->code)

pHeader->code保存您应该使用的通知代码值,pHeader->hwndFrom是被单击控件的句柄。

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

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

item.szUrl是您应该在调用 ShellExecute 调用打开时使用的 URL。

于 2012-05-23T22:22:01.283 回答
2

我找到了一种成功的方法来让它工作而不需要递归。消息循环似乎一直在连续循环中读取,如果您不使用正确的结构进行过滤,它将陷入无限递归。这对我有用。如果你有更好的输入,请做插件。

要采取的正确步骤。

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

使用了以下代码。

       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 其 url 路径,请使用 NMLINK 结构。

于 2012-05-24T18:48:35.253 回答
1

任何一个

  1. 您的OpenLink函数导致发送另一条消息(很可能),或者

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

  3. WM_NOTIFY您不是从,而是从上述案例的失败中获得此代码,或者

  4. DefWindowProc即使您已经处理了它,您仍会调用该消息。

尝试

  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;
于 2012-05-24T18:06:28.533 回答