/[winpt]/trunk/Src/wptBalloonPop.cpp
ViewVC logotype

Annotation of /trunk/Src/wptBalloonPop.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 340 - (hide annotations)
Sun Nov 27 13:15:07 2011 UTC (13 years, 3 months ago) by twoaday
File size: 7179 byte(s)


1 twoaday 340 /* wptBalloonPop.cpp - Balloon Popup-Box
2     * Copyright (C) 2009 Timo Schulz
3     *
4     * This file is part of WinPT.
5     *
6     * WinPT is free software; you can redistribute it and/or
7     * modify it under the terms of the GNU General Public License
8     * as published by the Free Software Foundation; either version 2
9     * of the License, or (at your option) any later version.
10     *
11     * WinPT is distributed in the hope that it will be useful,
12     * but WITHOUT ANY WARRANTY; without even the implied warranty of
13     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14     * General Public License for more details.
15     */
16    
17    
18     /* The idea is to use a balloon style 'error message' which
19     points to the control the error happened at. For instance
20     if no valid E-Mail address was entered, the balloon message
21     contains an error description with an arrow to the edit field
22     the address was supposed to be entered in. */
23    
24     #include <windows.h>
25     #include <stdio.h>
26     #include <time.h>
27    
28     #include "wptTypes.h"
29    
30     #define BT_WINDOWNAME "WinPT_BalloonPop"
31     #define BT_TIMER_IDENTIFIER 23
32     #define BT_IOFFSET 8
33    
34    
35     extern HINSTANCE glob_hinst;
36    
37     struct balloon_ctx_s {
38     LPCTSTR text;
39     LPCTSTR icon_name;
40     POINT pos;
41     HWND hwnd;
42     };
43     static struct balloon_ctx_s glob_msg;
44     static BOOL window_class_registered = FALSE;
45    
46    
47     static void
48     display_balloon_text (HWND hwnd, HDC hdc, const char *text)
49     {
50     RECT rc;
51     memset (&rc, 0, sizeof (rc));
52     GetClientRect(hwnd, &rc);
53    
54     POINT pts[3];
55     pts[0].x = rc.left + BT_IOFFSET;
56     pts[0].y = rc.top;
57     pts[1].x = pts[0].x;
58     pts[1].y = pts[0].y + BT_IOFFSET;
59     pts[2].x = pts[1].x + BT_IOFFSET;
60     pts[2].y = pts[1].y;
61    
62     // we merge three regions here:
63     // 1) basis
64     // 2) rounded box
65     // 3) arrow
66     HRGN hrgn = CreateRectRgn(0, 0, 0, 0);
67     HRGN hrgn1 = CreateRoundRectRgn(rc.left,
68     rc.top + BT_IOFFSET,
69     rc.right,
70     rc.bottom,
71     15, 15);
72     HRGN hrgn2 = CreatePolygonRgn(&pts[0], 3, ALTERNATE);
73     CombineRgn(hrgn, hrgn1, hrgn2, RGN_OR);
74    
75     // fill the region and draw a frame around it
76     FillRgn (hdc, hrgn, GetSysColorBrush(COLOR_INFOBK));
77     FrameRgn (hdc, hrgn, (HBRUSH)GetStockObject (DKGRAY_BRUSH), 1, 1);
78    
79     rc.top = rc.top + BT_IOFFSET*2;
80     rc.bottom = rc.bottom - BT_IOFFSET;
81     rc.left = rc.left + BT_IOFFSET;
82     rc.right = rc.right - BT_IOFFSET;
83    
84     // FIXME: calculate best position
85     HICON hicon = LoadIcon (NULL, glob_msg.icon_name);
86     if (hicon != NULL) {
87     DrawIconEx (hdc, 5, 20, hicon, 28, 28, 0, NULL, DI_NORMAL);
88     DestroyIcon (hicon);
89     }
90    
91     SetTextColor (hdc, GetSysColor (COLOR_INFOTEXT));
92     DrawText (hdc, text, strlen (text), &rc, DT_VCENTER + DT_NOCLIP);
93     }
94    
95    
96     // window procedure for the balloon tip.
97     static LRESULT CALLBACK
98     window_proc (HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
99     {
100     switch (msg) {
101     case WM_PAINT:
102     RECT rc;
103     GetWindowRect (hwnd, &rc);
104    
105     POINT curpos;
106     curpos.x = glob_msg.pos.x;
107     curpos.y = glob_msg.pos.y;
108    
109     rc.right = curpos.x - BT_IOFFSET + 6 + rc.right - rc.left;
110     rc.bottom = curpos.y + 20 + rc.bottom - rc.top;
111     rc.left = curpos.x - BT_IOFFSET + 6;
112     rc.top = curpos.y + 20;
113     MoveWindow (hwnd, rc.left, rc.top, rc.right - rc.left,
114     rc.bottom - rc.top, FALSE);
115    
116     HDC hdc;
117     PAINTSTRUCT ps;
118     hdc = BeginPaint (hwnd, &ps);
119    
120     LOGFONT lf;
121     memset (&lf, 0, sizeof (lf));
122     lf.lfHeight = 13;
123     lf.lfWeight = FW_NORMAL;
124     lf.lfQuality = ANTIALIASED_QUALITY;
125     strcpy (lf.lfFaceName, "MS Sans Serif");
126    
127     HFONT hfont;
128     hfont = CreateFontIndirect(&lf);
129     HFONT hfont_old;
130     hfont_old = (HFONT)SelectObject(ps.hdc, hfont);
131    
132     DrawText (ps.hdc, glob_msg.text, strlen (glob_msg.text),
133     &rc, DT_VCENTER+DT_NOCLIP+DT_CALCRECT);
134     rc.right = rc.right + 2*BT_IOFFSET;
135     rc.bottom = rc.bottom + 3*BT_IOFFSET;
136    
137     ShowWindow (hwnd, SW_SHOWNA);
138     MoveWindow(hwnd, rc.left, rc.top, rc.right - rc.left,
139     rc.bottom - rc.top, TRUE);
140     SetBkMode(ps.hdc, TRANSPARENT);
141     display_balloon_text (hwnd, ps.hdc, glob_msg.text);
142    
143     // restore old font object
144     SelectObject(ps.hdc, hfont_old);
145     DeleteObject (hfont);
146     EndPaint (hwnd, &ps);
147     break;
148    
149     case WM_LBUTTONUP:
150     ShowWindow (hwnd, SW_HIDE);
151     break;
152    
153     default:
154     return DefWindowProc (hwnd, msg, wparam, lparam);
155     }
156    
157     return FALSE;
158     }
159    
160    
161     /* Callback procedure to hide the baloon window after the
162     time has been expired */
163     static VOID CALLBACK
164     popup_timer_proc (HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
165     {
166     ShowWindow (hwnd, SW_HIDE);
167     }
168    
169    
170     /* Register our new window class */
171     static void
172     register_window_class (HINSTANCE hinst)
173     {
174     WNDCLASS wclass;
175     memset (&wclass, 0, sizeof (wclass));
176     wclass.style = CS_HREDRAW | CS_VREDRAW;
177     wclass.lpfnWndProc = window_proc;
178     wclass.hInstance = hinst;
179     wclass.lpszClassName = BT_WINDOWNAME;
180    
181     if (!RegisterClass (&wclass))
182     abort ();
183     }
184    
185    
186     static LPCTSTR
187     format_text (LPCTSTR string)
188     {
189     const int off = 12;
190     static char buf[2048];
191     int n = strlen (string), pos=0, i;
192    
193     memset (buf, 0, DIM (buf));
194     // FIXME: rewrite the function
195     if (n > 1600)
196     abort ();
197    
198     buf[pos++] = '\n';
199     for (i=0; i < off; i++)
200     buf[pos++] = ' ';
201     for (i=0; i < n; i++) {
202     buf[pos++] = string[i];
203     if (string[i] == '\n') {
204     for (int j=0; j < off; j++)
205     buf[pos++] = ' ';
206     }
207     }
208     buf[pos++] = '\n';
209     return buf;
210     }
211    
212    
213     /* Display a baloon message box at the given X- Y-coordinates */
214     HWND
215     show_balloon_msg_pos (HWND hparwnd, int millis, int x, int y,
216     LPCTSTR string, LPCTSTR icon_name)
217     {
218     if (!window_class_registered) {
219     register_window_class (glob_hinst);
220     window_class_registered = TRUE;
221     }
222    
223     // if no icon is requsted, print the text as it is.
224     if (!icon_name)
225     glob_msg.text = string;
226     else
227     glob_msg.text = format_text (string);
228     glob_msg.icon_name = icon_name;
229    
230     if (x > 0 && y > 0) { // use specific coordinates
231     glob_msg.pos.x = x;
232     glob_msg.pos.y = y;
233     }
234     else { // point to the lower left region of the control
235     RECT rect;
236     GetWindowRect (hparwnd, &rect);
237     glob_msg.pos.x = rect.left;
238     glob_msg.pos.y = rect.bottom - 20;
239     }
240    
241     // we use a persistent window for the balloon messages
242     // instead of destroy/create we hide the window whenever it
243     // is unused.
244     if (!glob_msg.hwnd) {
245     glob_msg.hwnd = CreateWindowEx (WS_EX_TOOLWINDOW | WS_EX_TOPMOST,
246     BT_WINDOWNAME, BT_WINDOWNAME,
247     WS_POPUP, 1, 1, 1, 1,
248     NULL, NULL, glob_hinst, NULL);
249     if (!glob_msg.hwnd)
250     BUG (0);
251     }
252    
253     // ensure 'parent' never loses focus.
254     HWND hwnd = glob_msg.hwnd;
255     ShowWindow (hwnd, SW_SHOW);
256     UpdateWindow (hwnd);
257     EnableWindow (hparwnd, TRUE);
258     SetActiveWindow (NULL);
259    
260     // show message for a fixed amount of time
261     SetTimer (hwnd, BT_TIMER_IDENTIFIER, millis, popup_timer_proc);
262    
263     return hwnd;
264     }
265    
266    
267     /* Show message at the default position for 5 seconds */
268     void
269     show_balloon_msg (HWND hparwnd, LPCTSTR string, LPCTSTR icon_name)
270     {
271     show_balloon_msg_pos (hparwnd, 5000, 0, 0, string ,icon_name);
272     }
273    
274    
275     /* Disable the message box (hide the window) */
276     void
277     balloon_msg_disable (void)
278     {
279     ShowWindow (glob_msg.hwnd, SW_HIDE);
280     }

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26