Subversion Repositories Games.Chess Giants

Rev

Rev 4 | Go to most recent revision | Details | Last modification | View Log | RSS feed

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