Jump to content

Problem: GUIRegisterMsg(...) with more than one GUI


 Share

Recommended Posts

I wrote today a little script to react on resume and suspend events and I have a little Problem. I took an example from this Forum which uses the GUIRegisterMsg(...) to receive the WM_POWERBROADCAST Messages from Windows.

This is my (simplified) script code:

Global $PwrStatus
Global Const $WM_POWERBROADCAST = 0x218
Global Const $PBT_APMRESUMESUSPEND = 0x7 ;Operation is resuming from a low-power state. This message is sent after PBT_APMRESUMEAUTOMATIC if the resume is triggered by user input, such as pressing a key.
Global Const $PBT_APMSUSPEND = 0x4 ; System is suspending operation.

GUIRegisterMsg($WM_POWERBROADCAST,"MY_WM_POWERBROADCAST")

Func MY_WM_POWERBROADCAST($hWnd, $uMsg, $wParam, $lParam)
    ; Beschreibgungen auf http://msdn.microsoft.com/en-us/library/aa373247(VS.85).aspx
    Select
        Case $wParam=$PBT_APMRESUMESUSPEND And $PwrStatus<>"resume" ;Wenn Status nicht gesetzt
                MsgBox(0,"Suspend","Windows wurde reaktiviert")
                ;$PwrStatus="resume"
        Case $wParam=$PBT_APMSUSPEND And $PwrStatus<>"suspend"
                MsgBox(0,"Suspend","Windows fährt in den Suspend")
                ;$PwrStatus="suspend"
        Case Else
    EndSelect
EndFunc

#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
Opt("GUIOnEventMode", 1)
#Region ### START Koda GUI section ### Form=
$Form1 = GUICreate("Form1", 413, 298, 237, 178)
#EndRegion ### END Koda GUI section ###

#Region ### START Koda GUI section ### Form=
$Form2 = GUICreate("Form2", 413, 298, 237, 178)
#EndRegion ### END Koda GUI section ###

#Region ### START Koda GUI section ### Form=
$Form3 = GUICreate("Form3", 413, 298, 237, 178)
#EndRegion ### END Koda GUI section ###

While 1
    sleep(100)
Wend

When I reduce the number of GUIs to one, all works very well.

But with two or more GUIs there seems to be a problem when I go to suspend mode. Before suspend the message box pops up for three times!!! When I resume from suspend mode, it's all ok. The message box pops up only for one time, how it should.

Why is the function called for three times and not only for one time before suspend? I solved this problem by adding the $PwrStatus variable.

Is there a better solution?

Edited by jojo1411
Link to comment
Share on other sites

This message is sent to all opened top level windows in the system. I guess you want to add logic to handle the first message and discard the remaining messages of the other windows in your application, or, make one top level GUI window the has multiple child windows.

Thanks Authenticity, for your quick answer. Now I understand why the function "MY_WM_POWERBROADCAST" was called for three times on suspend, but why only for one time on resume although i had created three parent GUIs on my first post?

My new code:

Global Const $WM_POWERBROADCAST = 0x218
Global Const $PBT_APMRESUMESUSPEND = 0x7 ;Operation is resuming from a low-power state. This message is sent after PBT_APMRESUMEAUTOMATIC if the resume is triggered by user input, such as pressing a key.
Global Const $PBT_APMSUSPEND = 0x4 ; System is suspending operation.

GUIRegisterMsg($WM_POWERBROADCAST,"MY_WM_POWERBROADCAST")

Func MY_WM_POWERBROADCAST($hWnd, $uMsg, $wParam, $lParam)
    ; Beschreibgungen auf http://msdn.microsoft.com/en-us/library/aa373247(VS.85).aspx
    Switch $wParam
        Case $PBT_APMRESUMESUSPEND
                MsgBox(0,"Suspend","Windows wurde reaktiviert")
        Case $PBT_APMSUSPEND
                MsgBox(0,"Suspend","Windows fährt in den Suspend")
        Case Else
    EndSwitch
EndFunc

#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
Opt("GUIOnEventMode", 1)
#Region ### START Koda GUI section ### Form=
$Form1 = GUICreate("Form1", 414, 299, 205, 124)
$Tab1 = GUICtrlCreateTab(16, 8, 249, 201)
GUICtrlSetResizing(-1, $GUI_DOCKWIDTH+$GUI_DOCKHEIGHT)
$TabSheet1 = GUICtrlCreateTabItem("TabSheet1")
$TabSheet2 = GUICtrlCreateTabItem("TabSheet2")
GUICtrlSetState(-1,$GUI_SHOW)
GUICtrlCreateTabItem("")
$Button1 = GUICtrlCreateButton("Button1", 280, 32, 75, 25)
$Button2 = GUICtrlCreateButton("Button2", 288, 240, 75, 25)
GUISetState(@SW_SHOW)
#EndRegion ### END Koda GUI section ###


#Region ### START Koda GUI section ### Form=
$Form2 = GUICreate("Form2", 200, 200, 137, 178, BitOR($WS_SYSMENU,$WS_CAPTION,$WS_CHILD,$WS_BORDER,$WS_CLIPSIBLINGS), -1, $Form1)
GUISetState(@SW_SHOW,$Form2)
#EndRegion ### END Koda GUI section ###

#Region ### START Koda GUI section ### Form=
$Form3 = GUICreate("Form3", 200, 200, 137, 178, BitOR($WS_SYSMENU,$WS_CAPTION,$WS_CHILD,$WS_BORDER,$WS_CLIPSIBLINGS), -1, $Form1)
GUISetState(@SW_SHOW,$Form3)
#EndRegion ### END Koda GUI section ###

While 1
    sleep(100)
Wend

I tried it with one parent and two child windows, and it worked. I get the message box appears only once on resume and suspend. Great!

But now the child windows are restricted to the parent window frame. Is this normal? Can I get them out there? There are also some graphic bugs when i move the child windows inside the parent window and the buttons from the parent form are overlayed. Sry for my bad english, but take a look at my attachment:

post-53744-12562045782129_thumb.jpg

Edited by jojo1411
Link to comment
Share on other sites

Sorry, I cannot replicate this glitch. Can you post the forms relevant code?

Try something like this:

#include <GUIConstantsEx.au3>
Opt("GUIOnEventMode", 1)

Global $hParent, $hChild1, $hChild2

$hParent = GUICreate("Parent", 300, 300)
GUICtrlCreateButton("&Button", 300/2-35/2, 300/2-12, 70, 23)
GUISetOnEvent($GUI_EVENT_CLOSE, "_Close")
GUISetState()

$hChild1 = GUICreate("Child1", 150, 150, -1, -1, -1, -1, $hParent)
GUICtrlCreateButton("&Button", 150/2-70/2, 150/2-12, 70, 24)
GUISetOnEvent($GUI_EVENT_CLOSE, "_Close")
GUISetState()

$hChild2 = GUICreate("Child2", 150, 150, -1, -1, -1, -1, $hParent)
GUICtrlCreateButton("&Button", 150/2-70/2, 150/2-12, 70, 24)
GUISetOnEvent($GUI_EVENT_CLOSE, "_Close")
GUISetState()

While 1
    Sleep(20)
WEnd

Func _Close()
    GUIDelete(@GUI_WinHandle)
    
    If @GUI_WinHandle = $hParent Then Exit
EndFunc
Link to comment
Share on other sites

Sorry, I cannot replicate this glitch. Can you post the forms relevant code?

Try something like this:

#include <GUIConstantsEx.au3>
Opt("GUIOnEventMode", 1)

Global $hParent, $hChild1, $hChild2

$hParent = GUICreate("Parent", 300, 300)
GUICtrlCreateButton("&Button", 300/2-35/2, 300/2-12, 70, 23)
GUISetOnEvent($GUI_EVENT_CLOSE, "_Close")
GUISetState()

$hChild1 = GUICreate("Child1", 150, 150, -1, -1, -1, -1, $hParent)
GUICtrlCreateButton("&Button", 150/2-70/2, 150/2-12, 70, 24)
GUISetOnEvent($GUI_EVENT_CLOSE, "_Close")
GUISetState()

$hChild2 = GUICreate("Child2", 150, 150, -1, -1, -1, -1, $hParent)
GUICtrlCreateButton("&Button", 150/2-70/2, 150/2-12, 70, 24)
GUISetOnEvent($GUI_EVENT_CLOSE, "_Close")
GUISetState()

While 1
    Sleep(20)
WEnd

Func _Close()
    GUIDelete(@GUI_WinHandle)
    
    If @GUI_WinHandle = $hParent Then Exit
EndFunc

I tried your code, but now I have no child windows anymore. It looks all good, but I have the same Problem like above with GUIRegisterMsg($WM_POWERBROADCAST,"MY_WM_POWERBROADCAST") and suspend. The function "MY_WM_POWERBROADCAST" is called once again for three times.

What do you mean with "forms relevant code"? I posted my whole code (incl. GuiCreate(..)).

Can you give me an answer to my questions above?

1. "Now I understand why the function "MY_WM_POWERBROADCAST" was called for three times on suspend, but why only for one time on resume although I had created three parent GUIs on my first post?"

2. "But now the child windows are restricted to the parent window frame. Is this normal? Can I get them out there?"

New code:

Global Const $WM_POWERBROADCAST = 0x218
Global Const $PBT_APMRESUMESUSPEND = 0x7 ;Operation is resuming from a low-power state. This message is sent after PBT_APMRESUMEAUTOMATIC if the resume is triggered by user input, such as pressing a key.
Global Const $PBT_APMSUSPEND = 0x4 ; System is suspending operation.

GUIRegisterMsg($WM_POWERBROADCAST,"MY_WM_POWERBROADCAST")

Func MY_WM_POWERBROADCAST($hWnd, $uMsg, $wParam, $lParam)
    ; Beschreibgungen auf http://msdn.microsoft.com/en-us/library/aa373247(VS.85).aspx
    Switch $wParam
        Case $PBT_APMRESUMESUSPEND
                MsgBox(0,"Suspend","Windows wurde reaktiviert")
        Case $PBT_APMSUSPEND
                MsgBox(0,"Suspend","Windows fährt in den Suspend")
        Case Else
    EndSwitch
EndFunc

#include <GUIConstantsEx.au3>
Opt("GUIOnEventMode", 1)

Global $hParent, $hChild1, $hChild2

$hParent = GUICreate("Parent", 300, 300)
GUICtrlCreateButton("&Button", 300/2-35/2, 300/2-12, 70, 23)
GUISetOnEvent($GUI_EVENT_CLOSE, "_Close")
GUISetState()

$hChild1 = GUICreate("Child1", 150, 150, -1, -1, -1, -1, $hParent)
GUICtrlCreateButton("&Button", 150/2-70/2, 150/2-12, 70, 24)
GUISetOnEvent($GUI_EVENT_CLOSE, "_Close")
GUISetState()

$hChild2 = GUICreate("Child2", 150, 150, -1, -1, -1, -1, $hParent)
GUICtrlCreateButton("&Button", 150/2-70/2, 150/2-12, 70, 24)
GUISetOnEvent($GUI_EVENT_CLOSE, "_Close")
GUISetState()

While 1
    Sleep(20)
WEnd

Func _Close()
    GUIDelete(@GUI_WinHandle)

    If @GUI_WinHandle = $hParent Then Exit
EndFunc
Link to comment
Share on other sites

1) First, I think that to send this message to all applications running on the system, the application has to process a message or thread loop, i.e. GetMessage(), PeekMessage() or as otherwise stated by the function description. So to send this message efficiently the system does something like:

PostMessage(HWND_BROADCAST, WM_POWERBROADCAST, PBT_APMSUSPEND, (LPARAM)someInternalValue);

...so because you got three top level windows you get notified 3 times. Read the function description and remarks.

About getting notified only once about this WM_POWERBROADCAST when system is resumed, I guess it's sending the message privately to each application's message loop, so the first created window is notified, and thus once.

One thing you can do and keep the program implementation as it was is to test something like:

Func MY_WM_POWERBROADCAST($hWnd, $uMsg, $wParam, $lParam)
    If $hWnd <> $Form1 Then Return $GUI_RUNDEFMSG

    Select
        Case $wParam=$PBT_APMRESUMESUSPEND And $PwrStatus<>"resume" ;Wenn Status nicht gesetzt
                MsgBox(0,"Suspend","Windows wurde reaktiviert")
                ;$PwrStatus="resume"
        Case $wParam=$PBT_APMSUSPEND And $PwrStatus<>"suspend"
                MsgBox(0,"Suspend","Windows fährt in den Suspend")
                ;$PwrStatus="suspend"
        Case Else
    EndSelect

    Return True ; Processing the message and prevent calling the default message procedure, read function description.
EndFunc

2) Even though the child windows are restricted hierarchically to the parent you don't have to code any logic that restrict them. For example, I've restricted them that by closing the parent window, the program exits, you don't have to.

About the buttons glitches, I can't replicate it, Niko: sorry.

Edited by Authenticity
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...