Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate
Photo

[solved] Win7: GDI+, after hibernation


  • Please log in to reply
14 replies to this topic
Learning one
  • Members
  • 1483 posts
  • Last active: Jan 02 2016 02:30 PM
  • Joined: 04 Apr 2009
I'm having problems with displaying layered windows after resuming from hibernation on Windows 7.
Test script below, which should be kept running before and after hibernation, demonstrates the problem.
;===Auto-execute========================================================================
Width := 300, Height := 300

RecreateAndShow:
Gui 1: Destroy
Gui 1: -Caption +E0x80000 +LastFound +ToolWindow +AlwaysOnTop +OwnDialogs
Gui 1: Show, NA
hwnd := WinExist()

pToken := Gdip_Startup()
hbm := CreateDIBSection(Width, Height), hdc := CreateCompatibleDC(), obm := SelectObject(hdc, hbm)
G := Gdip_GraphicsFromHDC(hdc), Gdip_SetSmoothingMode(G, 4), Gdip_SetInterpolationMode(G, 7)

pBrush := Gdip_CreateLineBrushFromRect(0, 0, Width, Height, 0xee5555ff, 0x555555ff)
Gdip_FillEllipse(G, pBrush, 0, 0, Width-1, Height-1)
Gdip_DeleteBrush(pBrush)

UpdateLayeredWindow(hwnd, hdc, (A_ScreenWidth-Width)/2, (A_ScreenHeight-Height)/2, Width, Height)
SelectObject(hdc, obm), DeleteObject(hbm), DeleteDC(hdc), Gdip_DeleteGraphics(G)
Gdip_Shutdown(pToken)
Return

;===Hotkeys=============================================================================
F1::
if DllCall("IsWindowVisible", "Ptr", hwnd)
   Gui 1: Hide
else
   Gui 1: Show, NA
return

F2::Gui 1: Show, NA
F3::Gui 1: Hide
F4:: MsgBox,,, % DllCall("IsWindowVisible", "Ptr", hwnd) ? "Window IS visible" : "Window IS NOT visible",1
F5::Gosub, RecreateAndShow	; solution number 2
Esc::ExitApp

;===Functions===========================================================================
#Include Gdip.ahk	; by Tic	http://www.autohotkey.com/forum/topic32238.html
On Windows XP and Windows Vista, everything works perfectly before and after hibernation - pressing F1 shows and hides blue circle.

On Windows 7, everything works perfectly before hibernation, but not any more after resuming from hibernation - pressing F1 doesn't show/hide blue circle - it's simply never displayed on the screen. Pressing F2, which should explicitly show window, doesn't help too. It's interesting that after pressing F2, and than pressing F4, MsgBox shows "Window IS visible" although window is not displayed on the screen. So window is visible but I can't see it?

Why window isn't displayed although it should be?
Am I doing something wrong?

If not, here are some solutions I figured out myself - monitor "resuming from suspended state" event (monitor WM_POWERBROADCAST = 0x218, wParam=7), and after such event occurs, automatically:
[*:3vcsmctn]reload entire script - good for simple scripts like this, but not for big scripts where one layered window is just one tiny component.
[*:3vcsmctn]don't reload entire script, just recreate and show layered window - effect like pressing F5 hotkey in test script above
[*:3vcsmctn]don't reload entire script, just update and show layered window - effect like pressing F5 hotkey in test script below. Contrary to test script above, which deletes bitmap, device context, graphics, and shuts down GDI+, on Auto-Execute end, this one is doing it on script exit.
;===Auto-execute========================================================================
Width := 300, Height := 300
OnExit, ExitSub

Gui 1: -Caption +E0x80000 +LastFound +ToolWindow +AlwaysOnTop +OwnDialogs
Gui 1: Show, hide
hwnd := WinExist()

pToken := Gdip_Startup()
hbm := CreateDIBSection(Width, Height), hdc := CreateCompatibleDC(), obm := SelectObject(hdc, hbm)
G := Gdip_GraphicsFromHDC(hdc), Gdip_SetSmoothingMode(G, 4), Gdip_SetInterpolationMode(G, 7)

pBrush := Gdip_CreateLineBrushFromRect(0, 0, Width, Height, 0xee5555ff, 0x555555ff)
Gdip_FillEllipse(G, pBrush, 0, 0, Width-1, Height-1)
Gdip_DeleteBrush(pBrush)

UpdateAndShow:
UpdateLayeredWindow(hwnd, hdc, (A_ScreenWidth-Width)/2, (A_ScreenHeight-Height)/2, Width, Height)
Gui 1: Show, NA
Return


;===Hotkeys=============================================================================
F1::
if DllCall("IsWindowVisible", "Ptr", hwnd)
   Gui 1: Hide
else
   Gui 1: Show, NA
return

F2::Gui 1: Show, NA
F3::Gui 1: Hide
F4:: MsgBox,,, % DllCall("IsWindowVisible", "Ptr", hwnd) ? "Window IS visible" : "Window IS NOT visible",1
F5::Gosub, UpdateAndShow	; solution number 3
Esc::ExitApp


;===Subroutines=========================================================================
ExitSub:
SelectObject(hdc, obm), DeleteObject(hbm), DeleteDC(hdc), Gdip_DeleteGraphics(G)
Gdip_Shutdown(pToken)
ExitApp


;===Functions===========================================================================
#Include Gdip.ahk	; by Tic	http://www.autohotkey.com/forum/topic32238.html
Which solution do you recommend? Do you have something better? Other ideas?
Thanks.

kenn
  • Members
  • 407 posts
  • Last active: Jan 14 2015 08:16 PM
  • Joined: 11 Oct 2010
It works ok in my computer (Win7). I think such problems come from drivers inconsistency. For example, my brother's network card driver doesn't work after hibernation.

tic
  • Members
  • 1934 posts
  • Last active: May 30 2018 08:13 PM
  • Joined: 22 Apr 2007
Just as a test, instead of hiding the window, try updating it with an hdc of a blank bitmap, and then for showing it, update with the real hdc.

Learning one
  • Members
  • 1483 posts
  • Last active: Jan 02 2016 02:30 PM
  • Joined: 04 Apr 2009
Thank you for replies. :)

Tic, I did a test you suggested. And yes, it works after resuming from hibernation.

Howewer, this technique, which deletes bitmap, device context, graphics, and shuts down GDI+ on script exit, (and which is also used in test script 2. in my first post), consumes much more memory that test script 1. from my first post, which is doing it on Auto-Execute end.

Therefore I can't say I'm happy with this solution - it's consuming too much memory for my taste... When we are working with 1 layered window, like here, it's not a big deal. But when working with 50 layered windows, which have bigger dimensions, than it's a big deal.

tic
  • Members
  • 1934 posts
  • Last active: May 30 2018 08:13 PM
  • Joined: 22 Apr 2007
No no I mean just create

hbmBlank := CreateDIBSection(Width, Height)
hdcBlank := CreateCompatibleDC()
obmBlank := SelectObject(hdcBlank, hbmBlank)

and then on hide try

UpdateLayeredWindow(hwnd, hdcBlank)

and on show do

UpdateLayeredWindow(hwnd, hdc)


Learning one
  • Members
  • 1483 posts
  • Last active: Jan 02 2016 02:30 PM
  • Joined: 04 Apr 2009
Tic, is this what you think?
;===Auto-execute========================================================================
Width := 800, Height := 800
OnExit, ExitSub

Gui 1: -Caption +E0x80000 +LastFound +ToolWindow +AlwaysOnTop +OwnDialogs
Gui 1: Show, hide
hwnd := WinExist()

pToken := Gdip_Startup()

;===Blue===
hbm := CreateDIBSection(Width, Height), hdc := CreateCompatibleDC(), obm := SelectObject(hdc, hbm)
G := Gdip_GraphicsFromHDC(hdc), Gdip_SetSmoothingMode(G, 4), Gdip_SetInterpolationMode(G, 7)
pBrush := Gdip_CreateLineBrushFromRect(0, 0, Width, Height, 0xee5555ff, 0x555555ff)
Gdip_FillEllipse(G, pBrush, 0, 0, Width-1, Height-1)
Gdip_DeleteBrush(pBrush), Gdip_DeleteGraphics(G)

Gdip_Shutdown(pToken)

;===Blank===
hbmBlank := CreateDIBSection(Width, Height), hdcBlank := CreateCompatibleDC(), obmBlank := SelectObject(hdcBlank, hbmBlank)

UpdateLayeredWindow(hwnd, hdc, (A_ScreenWidth-Width)/2, (A_ScreenHeight-Height)/2, Width, Height)
Gui 1: Show, NA
Return


;===Hotkeys=============================================================================
F2::UpdateLayeredWindow(hwnd, hdc)	; "show"
F3::UpdateLayeredWindow(hwnd, hdcBlank)	; fake hide (update with blank DC)
F4:: MsgBox,,, % DllCall("IsWindowVisible", "Ptr", hwnd) ? "Window IS visible" : "Window IS NOT visible",1	; it'll be visible all the time
Esc::ExitApp


;===Subroutines=========================================================================
ExitSub:
SelectObject(hdc, obm), DeleteObject(hbm), DeleteDC(hdc)		; Blue
SelectObject(hdcBlank, obmBlank), DeleteObject(hbmBlank), DeleteDC(hdcBlank)	; Blank
ExitApp


;===Functions===========================================================================
#Include Gdip.ahk				; by Tic	http://www.autohotkey.com/forum/topic32238.html
If yes, it's still consuming too much memory for my taste. When I run it, it consumes 5.915 K, and after I press F3, it consumes 8.424 K.

Now let's try script below
;===Auto-execute========================================================================
Width := 800, Height := 800

Gui 1: -Caption +E0x80000 +LastFound +ToolWindow +AlwaysOnTop +OwnDialogs
Gui 1: Show, NA
hwnd := WinExist()

pToken := Gdip_Startup()
hbm := CreateDIBSection(Width, Height), hdc := CreateCompatibleDC(), obm := SelectObject(hdc, hbm)
G := Gdip_GraphicsFromHDC(hdc), Gdip_SetSmoothingMode(G, 4), Gdip_SetInterpolationMode(G, 7)

pBrush := Gdip_CreateLineBrushFromRect(0, 0, Width, Height, 0xee5555ff, 0x555555ff)
Gdip_FillEllipse(G, pBrush, 0, 0, Width-1, Height-1)
Gdip_DeleteBrush(pBrush)
Gdip_Shutdown(pToken)

UpdateLayeredWindow(hwnd, hdc, (A_ScreenWidth-Width)/2, (A_ScreenHeight-Height)/2, Width, Height)
SelectObject(hdc, obm), DeleteObject(hbm), DeleteDC(hdc), Gdip_DeleteGraphics(G)
Return


;===Hotkeys=============================================================================
F2::Gui 1: Show, NA
F3::Gui 1: Hide
F4:: MsgBox,,, % DllCall("IsWindowVisible", "Ptr", hwnd) ? "Window IS visible" : "Window IS NOT visible",1
Esc::ExitApp

;===Functions===========================================================================
#Include Gdip.ahk				; by Tic	http://www.autohotkey.com/forum/topic32238.html
It's consuming just 3.468 K all the time.

So we have 8.424 K compared to 3.468 K. That's a big difference, and that's why I can't say I'm happy with this solution (updating with blank DC)...

tic
  • Members
  • 1934 posts
  • Last active: May 30 2018 08:13 PM
  • Joined: 22 Apr 2007
I guess we could decide what is more of a concern; memory or speed

You could try the same method in a different way to not use memory

F3::
hbmBlank := CreateDIBSection(Width, Height), hdcBlank := CreateCompatibleDC(), obmBlank := SelectObject(hdcBlank, hbmBlank)
UpdateLayeredWindow(hwnd, hdcBlank)   ; fake hide (update with blank DC)
SelectObject(hdcBlank, obmBlank), DeleteObject(hbmBlank), DeleteDC(hdcBlank)   ; Blank
return


Learning one
  • Members
  • 1483 posts
  • Last active: Jan 02 2016 02:30 PM
  • Joined: 04 Apr 2009
That's better. It consumes 5.915 K all the time and is fast enough. :)

Ok, so here the window is visible all the time, and when I want to hide it, I simply update it with blank DC. I'm interested what are the negative consequences if I chose this solution? Is there something I should know why this method shouldn't be used? Some warnings? What are the negative side-effects?

Thanks.

tic
  • Members
  • 1934 posts
  • Last active: May 30 2018 08:13 PM
  • Joined: 22 Apr 2007
I can't think of anything wrong with using this method. Not the cleanest, but not a big deal.
What happens if you do a normal hide, but when you want to show, instead of using WinShow, then use UpdateLayeredWindow to a specific position?

Learning one
  • Members
  • 1483 posts
  • Last active: Jan 02 2016 02:30 PM
  • Joined: 04 Apr 2009

I can't think of anything wrong with using this method. Not the cleanest, but not a big deal.

Ok. Thanks.

What happens if you do a normal hide, but when you want to show, instead of using WinShow, then use UpdateLayeredWindow to a specific position?

If I use just UpdateLayeredWindow, I can't see the window, which is expected. When I use Gui 1: Show, NA and than UpdateLayeredWindow than I can see the window and it works before and after hibernation.

Well, this is solved now. I can't say I'm happy with solutions, which are in fact just workarounds, but never mind.
Thank you Tic and Kenn! :) For others reference, here's how it should look:
;===Auto-execute========================================================================
Width := 800, Height := 800
OnExit, ExitSub

Gui 1: -Caption +E0x80000 +LastFound +ToolWindow +AlwaysOnTop +OwnDialogs
Gui 1: Show, hide
hwnd := WinExist()

pToken := Gdip_Startup()
hbm := CreateDIBSection(Width, Height), hdc := CreateCompatibleDC(), obm := SelectObject(hdc, hbm)
G := Gdip_GraphicsFromHDC(hdc), Gdip_SetSmoothingMode(G, 4), Gdip_SetInterpolationMode(G, 7)
pBrush := Gdip_CreateLineBrushFromRect(0, 0, Width, Height, 0xee5555ff, 0x555555ff)
Gdip_FillEllipse(G, pBrush, 0, 0, Width-1, Height-1)
Gdip_DeleteBrush(pBrush), Gdip_DeleteGraphics(G)
Gdip_Shutdown(pToken)

UpdateLayeredWindow(hwnd, hdc, (A_ScreenWidth-Width)/2, (A_ScreenHeight-Height)/2, Width, Height)
Gui 1: Show, NA
Return


;===Hotkeys=============================================================================
F2::	; show and update
Gui 1: Show, NA
UpdateLayeredWindow(hwnd, hdc)
return

F3::Gui 1: Hide
F4::MsgBox,,, % DllCall("IsWindowVisible", A_PtrSize ? "Ptr" : "UInt", hwnd) ? "Window IS visible" : "Window IS NOT visible",1
Esc::ExitApp


;===Subroutines=========================================================================
ExitSub:
SelectObject(hdc, obm), DeleteObject(hbm), DeleteDC(hdc)
ExitApp


;===Functions===========================================================================
#Include Gdip.ahk            ; by Tic   http://www.autohotkey.com/forum/topic32238.html
Kenn, when you wrote "It works ok in my computer (Win7)", was it 32-bit or 64-bit Win7? I'm testing on 64-bit. What about you? Was it 32-bit?

Leef_me
  • Moderators
  • 8510 posts
  • Last active: Sep 10 2015 05:50 AM
  • Joined: 08 Apr 2009
Hi Learning one

I'm using ahk_basic and w7 on a 64 bit system.
The reulst of this hotkey are always "Window IS NOT visible"

F4:: MsgBox,,, % DllCall("IsWindowVisible", "Ptr", hwnd) ? "Window IS visible" : "Window IS NOT visible",1

Do you have any idea why ?

Learning one
  • Members
  • 1483 posts
  • Last active: Jan 02 2016 02:30 PM
  • Joined: 04 Apr 2009
Hi Leef_me

Yes. In AutoHotkey Basic, Ptr must be replaced with UInt.
This will work on all AHK versions;
F4::MsgBox,,, % DllCall("IsWindowVisible", A_PtrSize ? "Ptr" : "UInt", hwnd) ? "Window IS visible" : "Window IS NOT visible",1
I updated my post. :wink:

Leef_me
  • Moderators
  • 8510 posts
  • Last active: Sep 10 2015 05:50 AM
  • Joined: 08 Apr 2009

Hi Leef_me

Yes. In AutoHotkey Basic, Ptr must be replaced with UInt.
This will work on all AHK versions;


Thanks.

kenn
  • Members
  • 407 posts
  • Last active: Jan 14 2015 08:16 PM
  • Joined: 11 Oct 2010

Kenn, when you wrote "It works ok in my computer (Win7)", was it 32-bit or 64-bit Win7? I'm testing on 64-bit. What about you? Was it 32-bit?

I tried it on both 32 bit and 64 bit, it works fine after hibernation on both of them.

Learning one
  • Members
  • 1483 posts
  • Last active: Jan 02 2016 02:30 PM
  • Joined: 04 Apr 2009
That's really strange. I tried it on my 64-bit Win7 and it doesn't work, but it works on your 64-bit Win7... :? :?:
Maybe the best explanation is what you wrote in your first post: "I think such problems come from drivers inconsistency."