Announcement

Collapse
No announcement yet.

Trying to figure out why I am not getting WM_POWERBROADCAST messages.

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Trying to figure out why I am not getting WM_POWERBROADCAST messages.

    I would have thought this would have worked in the dialog callback function:
    Code:
          CASE %WM_POWERBROADCAST
             WINBEEP(250,500)
             MSGBOX "%WM_POWERBROADCAST"

  • #2
    Have you called RegisterPowerSettingNotification

    Comment


    • #3
      Dave,

      If you ran a spy app on your WndProc you will see a very large number of messages going past. If you don't trap them they will just go to the default handler. You really only have to worry about the ones you trap and process.

      Depending on the method of showing a window or dialog, not all messages are available.
      hutch at movsd dot com
      The MASM Forum

      www.masm32.com

      Comment


      • #4
        Thanks guys! I think Stuart put his finger on it. I didn't see any mention of Register... when reading up on WM_POWERBROADCAST.

        Comment


        • #5
          You don't really need any registering to receive basic WM_POWERBROADCAST messages,
          just look for it in the main callback function, you will get Windows state like suspend and resume...

          If you need more specific message on particular hardware state then
          use RegisterPowerSettingNotification with the appropriate GUID.
          $GUID_MONITOR_POWER_ON for the monitor, $GUID_LIDSWITCH_STATE_CHANGE for a portable lid switch,
          $GUID_BATTERY_PERCENTAGE_REMAINING for battery percentage, ect.

          Comment


          • #6
            It's not really clear to me which $GUID I should use to get the PBT_APMSUSPEND, PBT_APMSUSPEND, PBT_APMRESUMEAUTOMATIC and PBT_APMRESUMESUSPEND events...
            Regards,
            Peter

            Comment


            • #7
              Hey Peter,
              You don't need any registration for those messages...

              Code:
              'An application may use SetSuspendState to transition the system from
              'the working state to the standby (sleep).
              'This function is similar to the SetSystemPowerState function.
              
              'If the system wakes due to user activity, the system will first broadcast
              'the PBT_APMRESUMEAUTOMATIC event followed by a PBT_APMRESUMESUSPEND event.
              'In addition, the system will turn on the display. Your application should reopen files
              'that it closed when the system entered the sleep state, and it should prepare for user input.
              
              '%PBT_APMQUERYSUSPEND         = &H0000
              '%PBT_APMQUERYSTANDBY         = &H0001
              '%PBT_APMQUERYSUSPENDFAILED   = &H0002
              '%PBT_APMQUERYSTANDBYFAILED   = &H0003
              '%PBT_APMSUSPEND              = &H0004
              '%PBT_APMSTANDBY              = &H0005
              '%PBT_APMRESUMECRITICAL       = &H0006
              '%PBT_APMRESUMESUSPEND        = &H0007
              '%PBT_APMRESUMESTANDBY        = &H0008
              '%PBTF_APMRESUMEFROMFAILURE   = &H00000001
              '%PBT_APMBATTERYLOW           = &H0009
              '%PBT_APMPOWERSTATUSCHANGE    = &H000A
              '%PBT_APMOEMEVENT             = &H000B
              '%PBT_APMRESUMEAUTOMATIC      = &H0012
              '_____________________________________________________________________________
              
              #COMPILE EXE '#Win#
              #INCLUDE "Win32Api.inc"
              #INCLUDE "CommCtrl.inc"
              
              '#RESOURCE MANIFEST, 1, "XPTheme.xml" ' or...
              #RESOURCE "D:\Basic\Bas\~~PbrDefault00.pbr" 'Set a valid resource
              
              DECLARE FUNCTION IsPwrSuspendAllowed LIB "PowrProf.DLL" ALIAS "IsPwrSuspendAllowed" () AS LONG
              
              DECLARE FUNCTION SetSuspendState LIB "PowrProf.DLL" ALIAS "SetSuspendState" _
              (BYVAL Hibernate AS LONG, BYVAL ForceCritical AS LONG, BYVAL DisableWakeEvent AS LONG) AS LONG
              
              GLOBAL hDlg AS DWORD
              
              %ButtonSuspend         = 101
              %ButtonExit            = 102
              %Edit                  = 201
              %TASKBAR_MIN_ALL       = 419
              '_____________________________________________________________________________
              
              SUB TextAdd(BYVAL sText AS STRING)
              
               'Move the caret to the end of text.
               'SendDlgItemMessage(hDlg, %Edit, %EM_SETSEL, -1, -1)
               SendDlgItemMessage(hDlg, %Edit, %EM_SETSEL, -2, -2)
              
               sText = sText & $CRLF 'Add a CRLF if needed
              
               'Insert the string at caret position.
               SendDlgItemMessage(hDlg, %Edit, %EM_REPLACESEL, %TRUE, BYVAL STRPTR(sText))
              
              END SUB
              '_____________________________________________________________________________
              
              CALLBACK FUNCTION DlgProc
               LOCAL Retval AS LONG
              
               SELECT CASE CBMSG
              
                 CASE %WM_INITDIALOG
                   TextAdd "Press suspend button to suspend..."
              
                 CASE %WM_COMMAND
                   SELECT CASE LOWRD(CBWPARAM)
              
                     CASE %ButtonExit
                       DIALOG END hDlg
              
                     CASE %ButtonSuspend
                       IF CBCTLMSG = %BN_CLICKED OR CBCTLMSG = 1 THEN
                         SendDlgItemMessage(hDlg, %Edit, %WM_SETTEXT, 0, BYVAL 0) 'Clear text
              
                         TextAdd"Suspend button clicked at " & TIME$
                         IF IsPwrSuspendAllowed THEN 'See also IsPwrHibernateAllowed for hibernation.
              
                           ShowWindow(hDlg, %SW_MINIMIZE) 'Use this so SW_RESTORE will work
              
                           SendMessage(FindWindow("Shell_TrayWnd", ""), %WM_COMMAND, %TASKBAR_MIN_ALL, 0)
              
                           'SetSuspendState: Suspends the system by shutting power down. Depending on the Hibernate
                           'parameter, the system either enters a suspend (sleep) state or hibernation (S4).
                           'Hibernate        [in] If TRUE, system hibernates. If FALSE, system is suspended.
                           'ForceCritical    [in] If TRUE, system suspends immediately. If FALSE, system broadcasts
                           '                      PBT_APMQUERYSUSPEND to each program to request permission.
                           Retval = SetSuspendState(%FALSE, %FALSE, %FALSE)
                           '*********************************************
                           '***                                       ***
                           '***    S U S P E N D  take place here     ***
                           '***                                       ***
                           '*********************************************
                           IF Retval THEN
                             TextAdd STRING$(50, "*")
                             TextAdd "Resuming from suspend at " & TIME$
                           ELSE
                             TextAdd "SetSuspendState error at " & TIME$
                           END IF
                           ShowWindow(hDlg, %SW_RESTORE)
                         ELSE
                           TextAdd "IsPwrSuspendAllowed returned FALSE."
                           TextAdd "Please setup computer for suspend."
                         END IF
                       END IF
                   END SELECT
              
                 CASE %WM_QUERYENDSESSION
              
                 CASE %WM_POWERBROADCAST
                   SELECT CASE CBWPARAM
              
                     CASE %PBT_APMQUERYSUSPEND
                       IF (CBLPARAM AND 1) THEN 'Hibernation do not have the force flag
                         TextAdd "WM_POWERBROADCAST-PBT_APMQUERYSUSPEND received at " & TIME$
                         'FUNCTION = %TRUE 'Return TRUE to grant the request to suspend.
                         'FUNCTION = %BROADCAST_QUERY_DENY 'To deny the request.
                         'EXIT FUNCTION
                       END IF
              
                     CASE %PBT_APMSUSPEND '1 - Received before suspend
                       'Smooth transitions to and from sleep are integral to the Windows Vista experience.
                       'The PBT_APMSUSPEND suspend notice is broadcast about two seconds prior to
                       'the sleep transition. The notice interval is shorter in Windows Vista than
                       'in earlier versions of Windows. Also, the standard configuration of Windows Vista
                       'prohibits applications from vetoing a sleep transition, although this behavior
                       'can be overridden through "Group Policy".
                       TextAdd "WM_POWERBROADCAST-PBT_APMSUSPEND received at " & TIME$ 'Not received under Vista.
              
                     CASE %PBT_APMRESUMEAUTOMATIC '2 - Received after suspend
                       TextAdd "WM_POWERBROADCAST-PBT_APMRESUMEAUTOMATIC received at " & TIME$
                       IF (CBLPARAM AND %PBTF_APMRESUMEFROMFAILURE) THEN
                         TextAdd "WM_POWERBROADCAST--PBTF_APMRESUMEFROMFAILURE received at " & TIME$
                       END IF
              
                     CASE %PBT_APMRESUMESUSPEND '3 - Received after first mouse move on dialog
                       TextAdd "WM_POWERBROADCAST-PBT_APMRESUMESUSPEND received at " & TIME$
                       IF (CBLPARAM AND %PBTF_APMRESUMEFROMFAILURE) THEN
                         TextAdd "WM_POWERBROADCAST--PBTF_APMRESUMEFROMFAILURE received at " & TIME$
                       END IF
              
                     CASE %PBT_APMRESUMECRITICAL
                       TextAdd "WM_POWERBROADCAST-PBT_APMRESUMECRITICAL received at " & TIME$
                       IF (CBLPARAM AND %PBTF_APMRESUMEFROMFAILURE) THEN
                         TextAdd "WM_POWERBROADCAST--PBTF_APMRESUMEFROMFAILURE received at " & TIME$
                       END IF
              
                     CASE %PBT_APMQUERYSUSPENDFAILED 'Suspension request denied.
                       TextAdd "WM_POWERBROADCAST--PBT_APMQUERYSUSPENDFAILED received at " & TIME$
              
                     CASE %PBT_APMQUERYSUSPENDFAILED
                       TextAdd "WM_POWERBROADCAST-PBT_APMQUERYSUSPENDFAILED received at " & TIME$
              
                     CASE %PBT_APMPOWERSTATUSCHANGE
                       TextAdd "WM_POWERBROADCAST-PBT_APMPOWERSTATUSCHANGE received at " & TIME$
              
                     CASE %PBT_APMBATTERYLOW
                       TextAdd "WM_POWERBROADCAST-PBT_APMBATTERYLOW received at " & TIME$
              
                   END SELECT
              
                END SELECT
              
              END FUNCTION
              '_____________________________________________________________________________
              
              FUNCTION PBMAIN()
               LOCAL hIconBig   AS DWORD
               LOCAL hIconSmall AS DWORD
              
               DIALOG FONT "Segoe UI", 9
               DIALOG NEW %HWND_DESKTOP, "PowerBroadcast", , , 275, 150, _
               %WS_CAPTION OR %WS_MINIMIZEBOX OR %WS_SYSMENU, %WS_EX_TOPMOST TO hDlg
              
               ExtractIconEx("Shell32.dll", 25, BYVAL VARPTR(hIconBig), BYVAL VARPTR(hIconSmall), 1)
               SetClassLong(hDlg, %GCL_HICONSM, hIconSmall) 'Set an icon
               SetClassLong(hDlg, %GCL_HICON, hIconBig) 'Set an icon
               SendMessage(hDlg, %WM_SETICON, %ICON_SMALL, hIconSmall)
               SendMessage(hDlg, %WM_SETICON, %ICON_BIG, hIconBig)
              
               CONTROL ADD BUTTON, hDlg, %ButtonSuspend, "&Suspend", 5, 5, 130, 15
              
               CONTROL ADD BUTTON, hDlg, %ButtonExit, "E&xit", 139, 5, 130, 15
              
               CONTROL ADD TEXTBOX, hDlg, %Edit , "", 5, 25, 265, 120, %WS_CHILD OR %WS_VISIBLE OR _
               %WS_TABSTOP OR %WS_HSCROLL OR %WS_VSCROLL OR %ES_LEFT OR %ES_MULTILINE OR _
               %ES_AUTOHSCROLL OR %ES_AUTOVSCROLL OR %ES_NOHIDESEL OR %ES_WANTRETURN, _
               %WS_EX_CLIENTEDGE OR %WS_EX_LEFT OR %WS_EX_LTRREADING OR %WS_EX_RIGHTSCROLLBAR
              
               DIALOG SHOW MODAL hDlg CALL DlgProc
              
               DestroyIcon(hIconSmall)
               DestroyIcon(hIconBig)
              
              END FUNCTION
              '_____________________________________________________________________________
              '
              Last edited by Pierre Bellisle; 19 Aug 2019, 08:35 AM.

              Comment


              • #8
                The problem I have is with this little program: https://forum.powerbasic.com/forum/u...ur-pc-to-sleep
                Because my PC doesn't always go to sleep (I set monitor off 15min, pc sleep 30min) due to some activity, I wrote a program to force PC to sleep
                Works wonderful mostly, but has some flaws:

                - After wake-up, keyboard and mouse hooks aren't always restored, so program is 'dead'. I expect some missing power messages?
                - Program sometimes loses topmost setting and gets behind other windows, must stay on top. (in Win7 it even got behind the desktop sometimes...)
                Regards,
                Peter

                Comment


                • #9
                  For the keyboard and mouse lost, first thing I would try would be to unHook before SetSuspendState() and reHook after.
                  For the zOrder, I woud minimize all applications before SetSuspendState() and restore them after.
                  I do something similar above, minimize all before and restore only my topmost application after.

                  Code:
                  %TASKBAR_MIN_ALL      = 419 '0x1A3
                  %TASKBAR_MIN_ALL_UNDO = 416 '0x1A0
                  %TASKBAR_HIDE         = 128 '0x80
                  %TASKBAR_UNHIDE       =  64 '0x40
                  
                  UnhookWindowsHookEx(hKeyHook)   : hKeyHook = 0
                  UnhookWindowsHookEx(hMouseHook) : hMouseHook = 0
                  SendMessage(FindWindow("Shell_TrayWnd", ""), %WM_COMMAND, %TASKBAR_MIN_ALL, 0) 'Minimize all app
                  
                  SetSuspendState(%FALSE, %TRUE, %FALSE)
                  
                  SendMessage(FindWindow("Shell_TrayWnd", ""), %WM_COMMAND, %TASKBAR_MIN_ALL_UNDO, 0) 'Restore all app
                  hKeyHook   = SetWindowsHookEx (%WH_KEYBOARD_LL, CODEPTR(KeyBoardHookProc), hInst, BYVAL 0)
                  hMouseHook = SetWindowsHookEx (%WH_MOUSE_LL   , CODEPTR(MouseHookProc)   , hInst, BYVAL 0)

                  Comment


                  • #10
                    Thanks,

                    I already do unhook before suspend. But for some reason the Sethook on resume doesn't work always...
                    Regards,
                    Peter

                    Comment


                    • #11
                      Hey Peter,

                      I'm a little confused because the link you gave unhook only in WM_DESTROY.

                      I guess we don't work on the same version... Am I right?

                      So, The SetHook() is failling...
                      Assuming the code you use is similar to the link,
                      what if you try to act only on PBT_APMRESUMEAUTOMATIC or PBT_APMRESUMESUSPEND but not both.

                      Comment


                      • #12
                        Oops!
                        That code is posted some time ago...
                        I will add latest version to that post...
                        Regards,
                        Peter

                        Comment


                        • #13
                          When you say "Sethook on resume doesn't work always.", what is the approximate ratio, 1/5, 1/50, 1/100?
                          Same question for the zOrder. Also, does both problems always appear together?

                          Just tried the code, pushing the sleep button on keyboard did fine...
                          Will do more tests...

                          I'm sure you are aware of this, here it is anyway. When you say program loses topmost, it's not when it is on the taskbar that is also topmost.

                          I did set %SHUTDOWNTIME to 200 to accelerate things, so far, so good...
                          I tried with the eyes on the taskbar and they stayed above on restore, more testing...


                          Is there a "hTimer = 0" missing in %PBT_APMSUSPEND, "If hTimer Then hTimer = timeKillEvent(hTimer)" ?

                          So far, I can't reproduce any problems.

                          The only little glitch is when I put the eyes on the taskbar and click this taskbar on an empty space, the eyes disappear behind it.

                          Comment


                          • #14
                            Pierre,

                            I didn't count how often it happened, but it's annoyingly often...
                            Z-order and focus don't seem to happen together.
                            To get back on top, it's enough to minimize or move the programs that are covering the eyes, move the eyes a little bit, and restore programs...
                            The moving behind the desktop/taskbar I also encountered, but I wasn't able to recover that without a program restart...

                            You are right about the missing hTimer = 0, I'll add that...
                            (I see I used: hTimer = timeKillEvent(hTimer), that should return TIMERR_NOERROR, is also '0')
                            Normally the program runs here in the right top corner of the screen.
                            Regards,
                            Peter

                            Comment


                            • #15
                              Yep, loosing keyboard and mouse is quite hard to live with. :-)

                              Finally, for the timer, re-reading the code, I don't think this "hTimer = 0" is needed.

                              MS say that timeSetEvent requires a corresponding timeKillEvent.
                              This look ok in code, except maybe if TimeSetEvent() fail and return an event creation error, but I think, it is very unlikely.

                              In my humble opinion, code is well written and everything seems in place.
                              I will do some more try to see if I can get at least one fail,
                              either lost mouse/keyboard or bad zOrder under Windows 7.

                              It's time to think "How could I reproduce this behavior?"
                              Finding the way will probably lead to the solution...


                              Comment


                              • #16
                                Hi Peter,
                                Still no error yet after many try...
                                If I may ask, did you have those problems on more than one machine?

                                Comment


                                • #17
                                  Yes on both machines I use it on...
                                  I will see if I can detect any regularity in the problems.

                                  (if you just let it run on your desktop, it will happen sooner or later. (and it's a nice distraction to see the eyes move... )
                                  Regards,
                                  Peter

                                  Comment


                                  • #18
                                    OK, I'm in for a couple of days more, hoping for a fail...

                                    Comment


                                    • #19
                                      Today (after a wake-up) is was somewhere halfway the z-order; behind some programs and above others.
                                      A short 'grab and move' solves it...
                                      Regards,
                                      Peter

                                      Comment


                                      • #20
                                        Still nothing on my side. I even mentally note the desktop zOrder before letting my pc going to sleep.
                                        Waiting for it...

                                        Curiosity: Did you try the %TASKBAR_MIN_ALL - %TASKBAR_MIN_ALL_UNDO code above?

                                        Comment

                                        Working...
                                        X