18
18
#define WEBDRIVER_IE_SCREENSHOTCOMMANDHANDLER_H_
19
19
20
20
#include " ../Browser.h"
21
- #include " ../HookProcessor.h"
22
21
#include " ../IECommandHandler.h"
23
22
#include " ../IECommandExecutor.h"
24
23
#include " logging.h"
@@ -129,76 +128,56 @@ class ScreenshotCommandHandler : public IECommandHandler {
129
128
LOG (DEBUG) << " Initial chrome sizes are (w, h): "
130
129
<< chrome_width << " , " << chrome_height;
131
130
132
- // Technically, we could use a custom structure here, and save a
133
- // few bytes, but RECT is already a well-known structure, and
134
- // one that is included as part of the Windows SDK, so we'll
135
- // leverage it.
136
- RECT max_image_dimensions;
137
- max_image_dimensions.left = 0 ;
138
- max_image_dimensions.top = 0 ;
139
- max_image_dimensions.right = document_info.width + chrome_width;
140
- max_image_dimensions.bottom = document_info.height + chrome_height;
131
+ int target_window_width = document_info.width + chrome_width;
132
+ int target_window_height = document_info.height + chrome_height;
141
133
142
134
// For some reason, this technique does not allow the user to resize
143
135
// the browser window to greater than SIZE_LIMIT x SIZE_LIMIT. This is pretty
144
136
// big, so we'll cap the allowable screenshot size to that.
145
137
//
146
138
// GDI+ limit after which it may report Generic error for some image types
147
139
int SIZE_LIMIT = 65534 ;
148
- if (max_image_dimensions. bottom > SIZE_LIMIT) {
140
+ if (target_window_height > SIZE_LIMIT) {
149
141
LOG (WARN) << " Required height is greater than limit. Truncating screenshot height." ;
150
- max_image_dimensions. bottom = SIZE_LIMIT;
151
- document_info.height = max_image_dimensions. bottom - chrome_height;
142
+ target_window_height = SIZE_LIMIT;
143
+ document_info.height = target_window_height - chrome_height;
152
144
}
153
- if (max_image_dimensions. right > SIZE_LIMIT) {
145
+ if (target_window_width > SIZE_LIMIT) {
154
146
LOG (WARN) << " Required width is greater than limit. Truncating screenshot width." ;
155
- max_image_dimensions. right = SIZE_LIMIT;
156
- document_info.width = max_image_dimensions. right - chrome_width;
147
+ target_window_width = SIZE_LIMIT;
148
+ document_info.width = target_window_width - chrome_width;
157
149
}
158
150
159
151
long original_width = browser->GetWidth ();
160
152
long original_height = browser->GetHeight ();
161
153
LOG (DEBUG) << " Initial browser window sizes are (w, h): "
162
154
<< original_width << " , " << original_height;
163
155
164
- bool requires_rezise = original_width <= max_image_dimensions.right ||
165
- original_height <= max_image_dimensions.bottom ;
166
-
167
- // The resize message is being ignored if the window appears to be
168
- // maximized. There's likely a way to bypass that. The kludgy way
169
- // is to unmaximize the window, then move on with setting the window
170
- // to the dimensions we really want. This is okay because we revert
171
- // back to the original dimensions afterward.
172
156
BOOL is_maximized = ::IsZoomed (ie_window_handle);
173
- if (is_maximized) {
174
- LOG (DEBUG) << " Window is maximized currently. Demaximizing." ;
175
- ::ShowWindow (ie_window_handle, SW_SHOWNORMAL);
176
- }
157
+ bool requires_resize = original_width < target_window_width ||
158
+ original_height < target_window_height;
159
+
160
+ if (requires_resize) {
161
+ // The resize message is being ignored if the window appears to be
162
+ // maximized. There's likely a way to bypass that. The kludgy way
163
+ // is to unmaximize the window, then move on with setting the window
164
+ // to the dimensions we really want. This is okay because we revert
165
+ // back to the original dimensions afterward.
166
+ if (is_maximized) {
167
+ LOG (DEBUG) << " Window is maximized currently. Demaximizing." ;
168
+ ::ShowWindow (ie_window_handle, SW_SHOWNORMAL);
169
+ }
177
170
178
- HookSettings hook_settings;
179
- hook_settings.window_handle = ie_window_handle;
180
- hook_settings.hook_procedure_name = " ScreenshotWndProc" ;
181
- hook_settings.hook_procedure_type = WH_CALLWNDPROC;
182
- hook_settings.communication_type = OneWay;
183
-
184
- HookProcessor hook;
185
- if (!hook.CanSetWindowsHook (ie_window_handle)) {
186
- LOG (WARN) << " Screenshot will be truncated! There is a mismatch "
187
- << " in the bitness between the driver and browser. In "
188
- << " particular, you are likely using a 32-bit "
189
- << " IEDriverServer.exe and a 64-bit version of IE." ;
171
+ RECT ie_window_rect;
172
+ ::GetWindowRect (ie_window_handle, &ie_window_rect);
173
+ ::SetWindowPos (ie_window_handle,
174
+ NULL ,
175
+ ie_window_rect.left,
176
+ ie_window_rect.top,
177
+ target_window_width,
178
+ target_window_height,
179
+ SWP_NOSENDCHANGING);
190
180
}
191
- hook.Initialize (hook_settings);
192
-
193
- hook.PushData (sizeof (max_image_dimensions), &max_image_dimensions);
194
- browser->SetWidth (max_image_dimensions.right );
195
-
196
- // Must re-push data because the resize causes a message to the
197
- // IE window, and reading the data clears the buffer.
198
- hook.PushData (sizeof (max_image_dimensions), &max_image_dimensions);
199
- browser->SetHeight (max_image_dimensions.bottom );
200
-
201
- hook.Dispose ();
202
181
203
182
// Capture the window's canvas to a DIB.
204
183
BOOL created = this ->image_ ->Create (document_info.width ,
@@ -216,12 +195,14 @@ class ScreenshotCommandHandler : public IECommandHandler {
216
195
LOG (WARN) << " PrintWindow API is not able to get content window screenshot" ;
217
196
}
218
197
219
- // Restore the browser to the original dimensions.
220
- if (is_maximized) {
221
- ::ShowWindow (ie_window_handle, SW_MAXIMIZE);
222
- } else {
223
- browser->SetHeight (original_height);
224
- browser->SetWidth (original_width);
198
+ if (requires_resize) {
199
+ // Restore the browser to the original dimensions.
200
+ if (is_maximized) {
201
+ ::ShowWindow (ie_window_handle, SW_MAXIMIZE);
202
+ } else {
203
+ browser->SetHeight (original_height);
204
+ browser->SetWidth (original_width);
205
+ }
225
206
}
226
207
227
208
this ->image_ ->ReleaseDC ();
@@ -352,84 +333,5 @@ class ScreenshotCommandHandler : public IECommandHandler {
352
333
353
334
} // namespace webdriver
354
335
355
- #ifdef __cplusplus
356
- extern " C" {
357
- #endif
358
-
359
- // This function is our message processor that we inject into the IEFrame
360
- // process. Its sole purpose is to process WM_GETMINMAXINFO messages and
361
- // modify the max tracking size so that we can resize the IEFrame window to
362
- // greater than the virtual screen resolution. All other messages are
363
- // delegated to the original IEFrame message processor. This function
364
- // uninjects itself immediately upon execution.
365
- LRESULT CALLBACK MinMaxInfoHandler (HWND hwnd,
366
- UINT message,
367
- WPARAM wParam,
368
- LPARAM lParam) {
369
- // Grab a reference to the original message processor.
370
- HANDLE original_message_proc = ::GetProp (hwnd,
371
- L" __original_message_processor__" );
372
- ::RemoveProp (hwnd, L" __original_message_processor__" );
373
-
374
- // Uninject this method.
375
- ::SetWindowLongPtr (hwnd,
376
- GWLP_WNDPROC,
377
- reinterpret_cast <LONG_PTR>(original_message_proc));
378
-
379
- if (WM_GETMINMAXINFO == message) {
380
- MINMAXINFO* minMaxInfo = reinterpret_cast <MINMAXINFO*>(lParam);
381
- RECT max_size;
382
- webdriver::HookProcessor::CopyDataFromBuffer (sizeof (RECT), reinterpret_cast <void *>(&max_size));
383
- minMaxInfo->ptMaxTrackSize .x = max_size.right ;
384
- minMaxInfo->ptMaxTrackSize .y = max_size.bottom ;
385
-
386
- // We're not going to pass this message onto the original message
387
- // processor, so we should return 0, per the documentation for
388
- // the WM_GETMINMAXINFO message.
389
- return 0 ;
390
- }
391
-
392
- // All other messages should be handled by the original message processor.
393
- return ::CallWindowProc (reinterpret_cast <WNDPROC>(original_message_proc),
394
- hwnd,
395
- message,
396
- wParam,
397
- lParam);
398
- }
399
-
400
- // Many thanks to sunnyandy for helping out with this approach. What we're
401
- // doing here is setting up a Windows hook to see incoming messages to the
402
- // IEFrame's message processor. Once we find one that's WM_GETMINMAXINFO,
403
- // we inject our own message processor into the IEFrame process to handle
404
- // that one message. WM_GETMINMAXINFO is sent on a resize event so the process
405
- // can see how large a window can be. By modifying the max values, we can allow
406
- // a window to be sized greater than the (virtual) screen resolution would
407
- // otherwise allow.
408
- //
409
- // See the discussion here: http://www.codeguru.com/forum/showthread.php?p=1889928
410
- LRESULT CALLBACK ScreenshotWndProc (int nCode, WPARAM wParam, LPARAM lParam) {
411
- CWPSTRUCT* call_window_proc_struct = reinterpret_cast <CWPSTRUCT*>(lParam);
412
- if (WM_COPYDATA == call_window_proc_struct->message ) {
413
- COPYDATASTRUCT* data = reinterpret_cast <COPYDATASTRUCT*>(call_window_proc_struct->lParam );
414
- webdriver::HookProcessor::CopyDataToBuffer (data->cbData , data->lpData );
415
- } else if (WM_GETMINMAXINFO == call_window_proc_struct->message ) {
416
- // Inject our own message processor into the process so we can modify
417
- // the WM_GETMINMAXINFO message. It is not possible to modify the
418
- // message from this hook, so the best we can do is inject a function
419
- // that can.
420
- LONG_PTR proc = ::SetWindowLongPtr (call_window_proc_struct->hwnd ,
421
- GWLP_WNDPROC,
422
- reinterpret_cast <LONG_PTR>(MinMaxInfoHandler));
423
- ::SetProp (call_window_proc_struct->hwnd,
424
- L" __original_message_processor__" ,
425
- reinterpret_cast <HANDLE>(proc));
426
- }
427
-
428
- return ::CallNextHookEx (NULL , nCode, wParam, lParam);
429
- }
430
-
431
- #ifdef __cplusplus
432
- }
433
- #endif
434
336
435
337
#endif // WEBDRIVER_IE_SCREENSHOTCOMMANDHANDLER_H_
0 commit comments