winhlp32: Prevent cursor flicker on mouse moves over richedit control.
authorDylan Smith <dylan.ah.smith@gmail.com>
Tue, 10 Mar 2009 19:19:59 +0000 (15:19 -0400)
committerAlexandre Julliard <julliard@winehq.org>
Wed, 11 Mar 2009 12:03:33 +0000 (13:03 +0100)
Previously the cursor was being set by winhlp32 on WM_MOUSEMOVE, then
the richedit control would change it again on WM_SETCURSOR.  Since the
cursor set in both of these places was different, the cursor would
flicker from being frequently changed.

The reason winhlp32 is setting the cursor, rather than letting the
richedit control set the cursor, is that winhlp32 needs the hand cursor
to be shown over a link.  My first instinct was to just add the CFE_LINK
effect to the link characters, however this also forced a colour for the
link that was inconsistent with native winhlp32.  Native winhlp32
doesn't seem to load any richedit dll, so this doesn't imply that there
is an undocumented way of changing the colour of characters with
CFE_LINK.

This patch has winhlp32 override the WNDPROC for the richedit control to
handle the WM_SETCURSOR.  It simply sets the cursor to the hand if the
cursor is over the link, otherwise it just calls the original richedit
window proc.

programs/winhlp32/winhelp.c
programs/winhlp32/winhelp.h

index d62649ffa85d30c342005bfbcae25c928f209cf9..db9769a55463c0eef8c417bcc9ef4ffcb7fa7b0f 100644 (file)
@@ -579,6 +579,64 @@ static void WINHELP_RememberPage(WINHELP_WINDOW* win, WINHELP_WNDPAGE* wpage)
     wpage->page->file->wRefCount++;
 }
 
+/***********************************************************************
+ *
+ *           WINHELP_FindLink
+ */
+static HLPFILE_LINK* WINHELP_FindLink(WINHELP_WINDOW* win, LPARAM pos)
+{
+    HLPFILE_LINK*           link;
+    POINTL                  mouse_ptl, char_ptl, char_next_ptl;
+    DWORD                   cp;
+
+    if (!win->page) return NULL;
+
+    mouse_ptl.x = (short)LOWORD(pos);
+    mouse_ptl.y = (short)HIWORD(pos);
+    cp = SendMessageW(GetDlgItem(win->hMainWnd, CTL_ID_TEXT), EM_CHARFROMPOS,
+                      0, (LPARAM)&mouse_ptl);
+
+    for (link = win->page->first_link; link; link = link->next)
+    {
+        if (link->cpMin <= cp && cp <= link->cpMax)
+        {
+            /* check whether we're at end of line */
+            SendMessageW(GetDlgItem(win->hMainWnd, CTL_ID_TEXT), EM_POSFROMCHAR,
+                         (LPARAM)&char_ptl, cp);
+            SendMessageW(GetDlgItem(win->hMainWnd, CTL_ID_TEXT), EM_POSFROMCHAR,
+                         (LPARAM)&char_next_ptl, cp + 1);
+            if (char_next_ptl.y != char_ptl.y || mouse_ptl.x >= char_next_ptl.x)
+                link = NULL;
+            break;
+        }
+    }
+    return link;
+}
+
+static LRESULT CALLBACK WINHELP_RicheditWndProc(HWND hWnd, UINT msg,
+                                                WPARAM wParam, LPARAM lParam)
+{
+    WINHELP_WINDOW *win = (WINHELP_WINDOW*) GetWindowLongPtr(GetParent(hWnd), 0);
+    DWORD messagePos;
+    POINT pt;
+    switch(msg)
+    {
+        case WM_SETCURSOR:
+            messagePos = GetMessagePos();
+            pt.x = (short)LOWORD(messagePos);
+            pt.y = (short)HIWORD(messagePos);
+            ScreenToClient(hWnd, &pt);
+            if (win->page && WINHELP_FindLink(win, MAKELPARAM(pt.x, pt.y)))
+            {
+                SetCursor(win->hHandCur);
+                return 0;
+            }
+            /* fall through */
+        default:
+            return CallWindowProcA(win->origRicheditWndProc, hWnd, msg, wParam, lParam);
+    }
+}
+
 /***********************************************************************
  *
  *           WINHELP_CreateHelpWindow
@@ -701,6 +759,8 @@ BOOL WINHELP_CreateHelpWindow(WINHELP_WNDPAGE* wpage, int nCmdShow, BOOL remembe
                                 0, 0, 0, 0, win->hMainWnd, (HMENU)CTL_ID_TEXT, Globals.hInstance, NULL);
         SendMessage(hTextWnd, EM_SETEVENTMASK, 0,
                     SendMessage(hTextWnd, EM_GETEVENTMASK, 0, 0) | ENM_MOUSEEVENTS);
+        win->origRicheditWndProc = (WNDPROC)SetWindowLongPtr(hTextWnd, GWLP_WNDPROC,
+                                                             (LONG_PTR)WINHELP_RicheditWndProc);
     }
 
     hIcon = (wpage->page) ? wpage->page->file->hIcon : NULL;
@@ -769,40 +829,6 @@ BOOL WINHELP_OpenHelpWindow(HLPFILE_PAGE* (*lookup)(HLPFILE*, LONG, ULONG*),
     return WINHELP_CreateHelpWindow(&wpage, nCmdShow, TRUE);
 }
 
-/***********************************************************************
- *
- *           WINHELP_FindLink
- */
-static HLPFILE_LINK* WINHELP_FindLink(WINHELP_WINDOW* win, LPARAM pos)
-{
-    HLPFILE_LINK*           link;
-    POINTL                  mouse_ptl, char_ptl, char_next_ptl;
-    DWORD                   cp;
-
-    if (!win->page) return NULL;
-
-    mouse_ptl.x = (short)LOWORD(pos);
-    mouse_ptl.y = (short)HIWORD(pos);
-    cp = SendMessageW(GetDlgItem(win->hMainWnd, CTL_ID_TEXT), EM_CHARFROMPOS,
-                      0, (LPARAM)&mouse_ptl);
-
-    for (link = win->page->first_link; link; link = link->next)
-    {
-        if (link->cpMin <= cp && cp <= link->cpMax)
-        {
-            /* check whether we're at end of line */
-            SendMessageW(GetDlgItem(win->hMainWnd, CTL_ID_TEXT), EM_POSFROMCHAR,
-                         (LPARAM)&char_ptl, cp);
-            SendMessageW(GetDlgItem(win->hMainWnd, CTL_ID_TEXT), EM_POSFROMCHAR,
-                         (LPARAM)&char_next_ptl, cp + 1);
-            if (char_next_ptl.y != char_ptl.y || mouse_ptl.x >= char_next_ptl.x)
-                link = NULL;
-            break;
-        }
-    }
-    return link;
-}
-
 /******************************************************************
  *             WINHELP_HandleTextMouse
  *
@@ -815,14 +841,7 @@ static BOOL WINHELP_HandleTextMouse(WINHELP_WINDOW* win, UINT msg, LPARAM lParam
 
     switch (msg)
     {
-    case WM_MOUSEMOVE:
-        if (WINHELP_FindLink(win, lParam))
-            SetCursor(win->hHandCur);
-        else
-            SetCursor(LoadCursor(0, IDC_ARROW));
-        break;
-
-     case WM_LBUTTONDOWN:
+    case WM_LBUTTONDOWN:
          if ((win->current_link = WINHELP_FindLink(win, lParam)))
              ret = TRUE;
          break;
index feaf6379bbdcfd441e3e64e7cc669eace96b1a8c..407089e304142c3814b7460881e1bee51254fe42 100644 (file)
@@ -80,6 +80,8 @@ typedef struct tagWinHelp
     HWND                hShadowWnd;
     HWND                hHistoryWnd;
 
+    WNDPROC             origRicheditWndProc;
+
     HFONT*              fonts;
     UINT                fonts_len;