Subversion Repositories Games.Chess Giants

Rev

Rev 5 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 pmbaty 1
// hyperlinks.c
2
 
3
#include <windows.h>
4
 
5
 
4 pmbaty 6
#ifdef UNICODE
7
#define LONGSTRING_PREFIX L
8
#else // !UNICODE
9
#define LONGSTRING_PREFIX
10
#endif // UNICODE
1 pmbaty 11
 
12
 
4 pmbaty 13
#define PROP_HYPERLINK_STRUCT LONGSTRING_PREFIX"_HyperlinkStruct"
14
#define PROP_HYPERLINKPARENT_STRUCT LONGSTRING_PREFIX"_HyperlinkParentStruct"
15
 
16
 
1 pmbaty 17
// standard hand cursor definition
18
#ifndef IDC_HAND
19
#define IDC_HAND 147
20
#endif
21
 
22
 
23
// hyperlink'ed static text control structure
24
typedef struct hyperlink_s
25
{
26
   HWND hWnd; // static text control window handle
27
   WNDPROC pfnOrigProc; // original static text control window procedure
28
   HFONT font; // underlined hypertext font used for this control
29
} hyperlink_t;
30
 
31
 
32
// hyperlink parent window structure
33
typedef struct hyperlinkparent_s
34
{
35
   HWND hWnd; // hyperlink parent window handle
36
   WNDPROC pfnOrigProc; // original static text control window parent procedure
37
} hyperlinkparent_t;
38
 
39
 
40
// hyperlink cursor
41
static HCURSOR hyperlink_cursor = NULL;
42
static LOGFONT hyperlink_logicalfont;
43
 
44
// hyperlinks.c function prototypes
45
void ConvertStaticToHyperlink (HWND hWndStatic);
46
static int WINAPI _HyperlinkParentProc (HWND hWnd, unsigned int message, WPARAM wParam, LPARAM lParam);
47
static int WINAPI _HyperlinkProc (HWND hWnd, unsigned int message, WPARAM wParam, LPARAM lParam);
48
 
49
 
50
void ConvertStaticToHyperlink (HWND hWndStatic)
51
{
52
   // subclass the parent so we can color the controls as we desire
53
 
54
   hyperlinkparent_t *hyperlinkparent;
55
   hyperlink_t *hyperlink;
56
 
57
   // first off, if the hand cursor isn't loaded yet, do it (this part is done once)
58
   if (hyperlink_cursor == NULL)
59
   {
60
      // since IDC_HAND is not available on all operating systems, we will load the arrow cursor if IDC_HAND is not present.
61
      hyperlink_cursor = LoadCursor (NULL, MAKEINTRESOURCE (IDC_HAND));
62
      if (hyperlink_cursor == NULL)
63
         hyperlink_cursor = LoadCursor (NULL, MAKEINTRESOURCE (IDC_ARROW)); // fallback cursor
64
   }
65
 
66
   // does this control belong to a window ?
67
   if (GetParent (hWndStatic) != NULL)
68
   {
69
      // mallocate space for a new hyperlink parent
70
      hyperlinkparent = (hyperlinkparent_t *) malloc (sizeof (hyperlinkparent_t));
71
      if (hyperlinkparent == NULL)
72
         return; // on failure, just return
73
 
74
      hyperlinkparent->hWnd = GetParent (hWndStatic); // save away the hyperlink parent's window handle
75
      hyperlinkparent->pfnOrigProc = (WNDPROC) GetWindowLong (GetParent (hWndStatic), GWL_WNDPROC); // get its current window procedure
76
 
77
      // has this parent NOT been already subclassed by another hyperlink ?
78
      if (hyperlinkparent->pfnOrigProc != (WNDPROC) _HyperlinkParentProc)
79
      {
80
         // save a pointer to the hyperlink structure in the window's properties and subclass it by replacing its window procedure by our own
81
         SetProp (GetParent (hWndStatic), PROP_HYPERLINKPARENT_STRUCT, (HANDLE) hyperlinkparent);
82
         SetWindowLongPtr (GetParent (hWndStatic), GWL_WNDPROC, (long) (WNDPROC) _HyperlinkParentProc);
83
      }
84
   }
85
 
86
   // mallocate space for a new hyperlink
87
   hyperlink = (hyperlink_t *) malloc (sizeof (hyperlink_t));
88
   if (hyperlink == NULL)
89
      return; // on failure, just return
90
 
91
   hyperlink->hWnd = hWndStatic; // get the static control's window handle
92
   hyperlink->pfnOrigProc = (WNDPROC) GetWindowLong (hyperlink->hWnd, GWL_WNDPROC); // get the static control's window procedure
93
 
94
   // create an updated font by adding an underline
95
   hyperlink->font = (HFONT) SendMessage (hyperlink->hWnd, WM_GETFONT, 0, 0);
96
   memset (&hyperlink_logicalfont, 0, sizeof (hyperlink_logicalfont));
97
   GetObject (hyperlink->font, sizeof (hyperlink_logicalfont), &hyperlink_logicalfont);
98
   hyperlink_logicalfont.lfUnderline = 1;
99
   hyperlink->font = CreateFontIndirect (&hyperlink_logicalfont);
100
   SendMessage (hyperlink->hWnd, WM_SETFONT, (WPARAM) hyperlink->font, 0);
101
 
102
   // make sure the static control will send event notifications to its window procedure
103
   SetWindowLong (hyperlink->hWnd, GWL_STYLE, GetWindowLong (hyperlink->hWnd, GWL_STYLE) | SS_NOTIFY);
104
 
105
   // save a pointer to the hyperlink structure in the window's properties and subclass it by replacing its window procedure by our own
106
   SetProp (hyperlink->hWnd, PROP_HYPERLINK_STRUCT, (HANDLE) hyperlink);
107
   SetWindowLongPtr (hyperlink->hWnd, GWL_WNDPROC, (long) (WNDPROC) _HyperlinkProc);
108
 
109
   return; // finished transforming the static text control
110
}
111
 
112
 
113
static int WINAPI _HyperlinkParentProc (HWND hWnd, unsigned int message, WPARAM wParam, LPARAM lParam)
114
{
115
   // this function hooks the hyperlink parent's control drawing messages so as to draw hyperlinks differently from normal static controls
116
 
117
   hyperlinkparent_t *hyperlinkparent;
118
   LRESULT result;
119
 
120
   // get a pointer to the hyperlink structure
121
   hyperlinkparent = (hyperlinkparent_t *) GetProp (hWnd, PROP_HYPERLINKPARENT_STRUCT);
122
   if (hyperlinkparent == NULL)
123
      return (DefWindowProc (hWnd, message, wParam, lParam)); // consistency check
124
 
125
   // are we drawing a static control ?
126
   if (message == WM_CTLCOLORSTATIC)
127
   {
128
      result = CallWindowProc (hyperlinkparent->pfnOrigProc, hWnd, message, wParam, lParam); // call the window procedure normally
129
      if ((WNDPROC) GetWindowLong ((HWND) lParam, GWL_WNDPROC) == (WNDPROC) _HyperlinkProc)
130
         SetTextColor ((HDC) wParam, RGB (0, 0, 192)); // but notify the parent to draw this text in blue if it's one of our hyperlinks
131
      return (result); // and return the original window proc return result
132
   }
133
 
134
   // now call the original window procedure to let things go normally
135
   return (CallWindowProc (hyperlinkparent->pfnOrigProc, hWnd, message, wParam, lParam));
136
}
137
 
138
 
139
static int WINAPI _HyperlinkProc (HWND hWnd, unsigned int message, WPARAM wParam, LPARAM lParam)
140
{
141
   // this function hooks the messages directed to the static text control that we turned into a hyperlink
142
 
143
   hyperlink_t *hyperlink;
144
 
145
   // get a pointer to the hyperlink structure
146
   hyperlink = (hyperlink_t *) GetProp (hWnd, PROP_HYPERLINK_STRUCT);
147
   if (hyperlink == NULL)
148
      return (DefWindowProc (hWnd, message, wParam, lParam)); // consistency check
149
 
150
   // is the mouse moving inside the static control ?
151
   if (message == WM_SETCURSOR)
152
   {
153
      if (hyperlink_cursor != NULL)
154
         SetCursor (hyperlink_cursor); // set the static control cursor to be the pointing hand, if we have it
155
 
156
      return (1); // halt further processing on this message
157
   }
158
 
159
   // else are we destroying the static control ?
160
   else if (message == WM_DESTROY)
161
   {
162
      if (hyperlink != NULL)
5 pmbaty 163
      {
164
         SetWindowLongPtr (hWnd, GWL_WNDPROC, (long) hyperlink->pfnOrigProc); // restore the original static control procedure
165
         RemoveProp (hWnd, PROP_HYPERLINK_STRUCT); // and remove the static control property where we used to save it
1 pmbaty 166
         free (hyperlink); // free the hyperlink structure
5 pmbaty 167
         hyperlink = NULL;
168
      }
169
 
170
      return (DefWindowProc (hWnd, message, wParam, lParam)); // consistency fallback
1 pmbaty 171
   }
172
 
173
   // now call the original static control procedure to let things go normally
174
   return (CallWindowProc (hyperlink->pfnOrigProc, hWnd, message, wParam, lParam));
175
}