VirtualBox

source: vbox/trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxHelpers.cpp@ 34079

Last change on this file since 34079 was 34025, checked in by vboxsync, 14 years ago

VBoxTray: Implemented global message registration/handling mechanism, added a global message for sending external messages to the systray balloon, refactoring, some bugfixes.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 9.8 KB
Line 
1/** @file
2 * helpers - Guest Additions Service helper functions
3 */
4
5/*
6 * Copyright (C) 2006-2010 Oracle Corporation
7 *
8 * This file is part of VirtualBox Open Source Edition (OSE), as
9 * available from http://www.virtualbox.org. This file is free software;
10 * you can redistribute it and/or modify it under the terms of the GNU
11 * General Public License (GPL) as published by the Free Software
12 * Foundation, in version 2 as it comes in the "COPYING" file of the
13 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
14 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
15 */
16
17#include <malloc.h>
18#include <windows.h>
19
20#include <iprt/string.h>
21#include <VBox/VBoxGuestLib.h>
22
23#include <VBoxGuestInternal.h>
24
25#include "VBoxHelpers.h"
26#include "resource.h"
27
28
29
30/**
31 * Attempt to force Windows to reload the cursor image by attaching to the
32 * thread of the window currently under the mouse, hiding the cursor and
33 * showing it again. This could fail to work in any number of ways (no
34 * window under the cursor, the cursor has moved to a different window while
35 * we are processing), but we just accept this, as the cursor will be reloaded
36 * at some point anyway.
37 */
38void hlpReloadCursor(void)
39{
40 POINT mousePos;
41 HWND hWin;
42 DWORD hThread, hCurrentThread;
43
44 GetCursorPos(&mousePos);
45 hWin = WindowFromPoint(mousePos);
46 if (hWin)
47 {
48 hThread = GetWindowThreadProcessId(hWin, NULL);
49 hCurrentThread = GetCurrentThreadId();
50 if (hCurrentThread != hThread)
51 AttachThreadInput(hCurrentThread, hThread, TRUE);
52 }
53 ShowCursor(false);
54 ShowCursor(true);
55 if (hWin && (hCurrentThread != hThread))
56 AttachThreadInput(hCurrentThread, hThread, FALSE);
57}
58
59static unsigned hlpNextAdjacentRectXP(RECTL *paRects, unsigned nRects, unsigned uRect)
60{
61 unsigned i;
62 for (i = 0; i < nRects; i++)
63 {
64 if (paRects[uRect].right == paRects[i].left)
65 return i;
66 }
67 return ~0;
68}
69
70static unsigned hlpNextAdjacentRectXN(RECTL *paRects, unsigned nRects, unsigned uRect)
71{
72 unsigned i;
73 for (i = 0; i < nRects; i++)
74 {
75 if (paRects[uRect].left == paRects[i].right)
76 return i;
77 }
78 return ~0;
79}
80
81static unsigned hlpNextAdjacentRectYP(RECTL *paRects, unsigned nRects, unsigned uRect)
82{
83 unsigned i;
84 for (i = 0; i < nRects; i++)
85 {
86 if (paRects[uRect].bottom == paRects[i].top)
87 return i;
88 }
89 return ~0;
90}
91
92static unsigned hlpNextAdjacentRectYN(RECTL *paRects, unsigned nRects, unsigned uRect)
93{
94 unsigned i;
95 for (i = 0; i < nRects; i++)
96 {
97 if (paRects[uRect].top == paRects[i].bottom)
98 return i;
99 }
100 return ~0;
101}
102
103void hlpResizeRect(RECTL *paRects, unsigned nRects, unsigned uPrimary,
104 unsigned uResized, int iNewWidth, int iNewHeight)
105{
106 DDCLOG(("nRects %d, iPrimary %d, iResized %d, NewWidth %d, NewHeight %d\n", nRects, uPrimary, uResized, iNewWidth, iNewHeight));
107
108 RECTL *paNewRects = (RECTL *)alloca (sizeof (RECTL) * nRects);
109 memcpy (paNewRects, paRects, sizeof (RECTL) * nRects);
110 paNewRects[uResized].right += iNewWidth - (paNewRects[uResized].right - paNewRects[uResized].left);
111 paNewRects[uResized].bottom += iNewHeight - (paNewRects[uResized].bottom - paNewRects[uResized].top);
112
113 /* Verify all pairs of originally adjacent rectangles for all 4 directions.
114 * If the pair has a "good" delta (that is the first rectangle intersects the second)
115 * at a direction and the second rectangle is not primary one (which can not be moved),
116 * move the second rectangle to make it adjacent to the first one.
117 */
118
119 /* X positive. */
120 unsigned iRect;
121 for (iRect = 0; iRect < nRects; iRect++)
122 {
123 /* Find the next adjacent original rect in x positive direction. */
124 unsigned iNextRect = hlpNextAdjacentRectXP(paRects, nRects, iRect);
125 DDCLOG(("next %d -> %d\n", iRect, iNextRect));
126
127 if (iNextRect == ~0 || iNextRect == uPrimary)
128 {
129 continue;
130 }
131
132 /* Check whether there is an X intersection between these adjacent rects in the new rectangles
133 * and fix the intersection if delta is "good".
134 */
135 int delta = paNewRects[iRect].right - paNewRects[iNextRect].left;
136
137 if (delta != 0)
138 {
139 DDCLOG(("XP intersection right %d left %d, diff %d\n",
140 paNewRects[iRect].right, paNewRects[iNextRect].left,
141 delta));
142
143 paNewRects[iNextRect].left += delta;
144 paNewRects[iNextRect].right += delta;
145 }
146 }
147
148 /* X negative. */
149 for (iRect = 0; iRect < nRects; iRect++)
150 {
151 /* Find the next adjacent original rect in x negative direction. */
152 unsigned iNextRect = hlpNextAdjacentRectXN(paRects, nRects, iRect);
153 DDCLOG(("next %d -> %d\n", iRect, iNextRect));
154
155 if (iNextRect == ~0 || iNextRect == uPrimary)
156 {
157 continue;
158 }
159
160 /* Check whether there is an X intersection between these adjacent rects in the new rectangles
161 * and fix the intersection if delta is "good".
162 */
163 int delta = paNewRects[iRect].left - paNewRects[iNextRect].right;
164
165 if (delta != 0)
166 {
167 DDCLOG(("XN intersection left %d right %d, diff %d\n",
168 paNewRects[iRect].left, paNewRects[iNextRect].right,
169 delta));
170
171 paNewRects[iNextRect].left += delta;
172 paNewRects[iNextRect].right += delta;
173 }
174 }
175
176 /* Y positive (in the computer sense, top->down). */
177 for (iRect = 0; iRect < nRects; iRect++)
178 {
179 /* Find the next adjacent original rect in y positive direction. */
180 unsigned iNextRect = hlpNextAdjacentRectYP(paRects, nRects, iRect);
181 DDCLOG(("next %d -> %d\n", iRect, iNextRect));
182
183 if (iNextRect == ~0 || iNextRect == uPrimary)
184 {
185 continue;
186 }
187
188 /* Check whether there is an Y intersection between these adjacent rects in the new rectangles
189 * and fix the intersection if delta is "good".
190 */
191 int delta = paNewRects[iRect].bottom - paNewRects[iNextRect].top;
192
193 if (delta != 0)
194 {
195 DDCLOG(("YP intersection bottom %d top %d, diff %d\n",
196 paNewRects[iRect].bottom, paNewRects[iNextRect].top,
197 delta));
198
199 paNewRects[iNextRect].top += delta;
200 paNewRects[iNextRect].bottom += delta;
201 }
202 }
203
204 /* Y negative (in the computer sense, down->top). */
205 for (iRect = 0; iRect < nRects; iRect++)
206 {
207 /* Find the next adjacent original rect in x negative direction. */
208 unsigned iNextRect = hlpNextAdjacentRectYN(paRects, nRects, iRect);
209 DDCLOG(("next %d -> %d\n", iRect, iNextRect));
210
211 if (iNextRect == ~0 || iNextRect == uPrimary)
212 {
213 continue;
214 }
215
216 /* Check whether there is an Y intersection between these adjacent rects in the new rectangles
217 * and fix the intersection if delta is "good".
218 */
219 int delta = paNewRects[iRect].top - paNewRects[iNextRect].bottom;
220
221 if (delta != 0)
222 {
223 DDCLOG(("YN intersection top %d bottom %d, diff %d\n",
224 paNewRects[iRect].top, paNewRects[iNextRect].bottom,
225 delta));
226
227 paNewRects[iNextRect].top += delta;
228 paNewRects[iNextRect].bottom += delta;
229 }
230 }
231
232 memcpy (paRects, paNewRects, sizeof (RECTL) * nRects);
233 return;
234}
235
236int hlpShowBalloonTip(HINSTANCE hInst, HWND hWnd, UINT uID,
237 const char *pszMsg, const char *pszTitle,
238 UINT uTimeout, DWORD dwInfoFlags)
239{
240 NOTIFYICONDATA niData;
241 ZeroMemory(&niData, sizeof(NOTIFYICONDATA));
242 niData.cbSize = sizeof(NOTIFYICONDATA);
243 niData.uFlags = NIF_INFO; /* Display a balloon notification. */
244 niData.hWnd = hWnd;
245 niData.uID = uID;
246 /* If not timeout set, set it to 5sec. */
247 if (uTimeout == 0)
248 uTimeout = 5000;
249 niData.uTimeout = uTimeout;
250 /* If no info flag (info, warning, error) set,
251 * set it to info by default. */
252 if (dwInfoFlags == 0)
253 dwInfoFlags = NIIF_INFO;
254 niData.dwInfoFlags = dwInfoFlags;
255
256 /* Do we want to have */
257
258 /* Get running OS version. */
259 OSVERSIONINFO osInfo;
260 osInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
261 if (FALSE == GetVersionEx(&osInfo))
262 return RTErrConvertFromWin32(GetLastError());
263
264 /* Is the current OS supported (at least WinXP) for displaying
265 * our own icon and do we actually *want* to display our own stuff? */
266 if ( osInfo.dwMajorVersion >= 5
267 && (dwInfoFlags & NIIF_INFO))
268 {
269 /* Load (or retrieve handle of) the app's icon. */
270 HICON hIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_VIRTUALBOX));
271 if (hIcon)
272 niData.dwInfoFlags = NIIF_USER; /* Use an own notification icon. */
273
274 if ( osInfo.dwMajorVersion == 5
275 && osInfo.dwMinorVersion == 1) /* WinXP. */
276 {
277 /* Use an own icon instead of the default one. */
278 niData.hIcon = hIcon;
279 }
280 else if (osInfo.dwMajorVersion == 6) /* Vista and up. */
281 {
282 /* Use an own icon instead of the default one. */
283 niData.dwInfoFlags |= NIIF_LARGE_ICON; /* Use a large icon if available! */
284 niData.hIcon = hIcon;
285 niData.hBalloonIcon = hIcon;
286 }
287 }
288 else
289 {
290 /* This might be a warning, error message or a to old OS. Use the
291 * standard icons provided by Windows (if any). */
292 }
293
294 strcpy(niData.szInfo, pszMsg ? pszMsg : "-");
295 strcpy(niData.szInfoTitle, pszTitle ? pszTitle : "Information");
296
297 if (!Shell_NotifyIcon(NIM_MODIFY, &niData))
298 {
299 DWORD dwErr = GetLastError();
300 return RTErrConvertFromWin32(dwErr);
301 }
302 return VINF_SUCCESS;
303}
304
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette