Jump to content

Overlap a menu of an app by GUI meni


Recommended Posts

All,

I'm using the Windows application Picasa 3 and I need to overlap its native menu by a custom GUI menu which has to stay always in front of Picasa window. I manage to do it by means of the following simple code:

$hGUI_Arch_menu = GUICreate($menuname, @DesktopWidth, 20,-3,0,-1,$WS_EX_TOOLWINDOW,$hwndPicasa)

There are however few serious limitations. As the GUI menu has to overlap *ALWAYS* the native menu as it would be hooked to Picasa, I managed to make it work only if the Picasa window is maximized and therefore it cannot be moved on screen or restored to "not-maximized" status. I can live with it, but, the GUI menu appears also on top of any other window, when Picasa app is behind other windows. That is a serious threat to the general functionality of this solution. I would expect that specifying a handle to the parent window ($hwndPicasa), the GUI will follow the status of the Picasa window, but it is not the case.

Now, the questions:

1- is it possible to make the GUI menu follow the front/back status of Picasa window, so to go back of other windows (when Picasa is behind other windows), but continuing to stay in front of the Picasa window?

2- is it possible to "hook" the GUI menu to the Picasa window in the way it follows its position and width?

THE WHOLE STORY: Picasa is a freeware, discarded by Google, but functional and installable. Its user interface is not editable, so it is impossible to remove or add options to the menu. Unfortunately, in the role I use it (as a front end of a big distributable archive of pics and videos dedicated to the animals' advocacy), many default functionalities exposed in menu are potential breakdowns of the archive's integrity, therefore, the only solution I've found it to cover the whole main menu with the more adequate replacement menu.

Thanks in advance for any suggestion,

Kind regards,

Bruno 

 

 

 

 

Link to post
Share on other sites
2 hours ago, Dan_555 said:

I would try it with the Ressouce Hacker

It can work in some cases, while in others it does not.

Make a backup copy of the exe or dll which you are editing.

Thanks, but in this case it doesn't function. To be more precise, it doesn't show any menu option. Apparently, the menu is constructed outside of the resources.

Link to post
Share on other sites
2 hours ago, Nine said:

Have you tried to manage the menu with _GUICtrlMenu_* functions ?

Thanks for your reply. I manage the menu with the mentioned functions. The problem is in the GUI window of the menu itself...

BTW, perhaps I misunderstood your question... if you're proposing that I manage the native menu of Picasa with the GUI functions, it doesn't work as the Picasa menu is not following the Windows standards...

Edited by BrunoStivicevic
Link to post
Share on other sites
1 hour ago, BrunoStivicevic said:

if you're proposing that I manage the native menu of Picasa with the GUI functions

Yes that was the purpose of my question, since I don't use nor know Picasa.  Have you explore UIAutomation ?  Maybe you could change menu items, and monitor menu selection ?  Not sure if it is possible though...Good luck.

Link to post
Share on other sites
1 hour ago, Nine said:

Yes that was the purpose of my question, since I don't use nor know Picasa.  Have you explore UIAutomation ?  Maybe you could change menu items, and monitor menu selection ?  Not sure if it is possible though...Good luck.

Thanks for your reply. Nothing works with Picasa menu as it is non standard... I hope someone will answer on the GUI window part of the question.

Link to post
Share on other sites

Something to play with :

#include <GUIConstantsEx.au3>
#include <MsgBoxConstants.au3>
#include <WindowsConstants.au3>

Global $g_hGUI, $g_hGUI2

Example()

Func Example()
    $g_hGUI = GUICreate("Picasa", 400, 200, -1, -1, $WS_OVERLAPPEDWINDOW)
    Local $aPos = WinGetPos($g_hGUI)

    Local $idButton_1 = GUICtrlCreateButton("Button 1", 100, 170, 85, 25)
    Local $idButton_Close = GUICtrlCreateButton("Close", 215, 170, 85, 25)

    $g_hGUI2 = GUICreate("Covering PopUp", 50, 50, $aPos[0], $aPos[1], $WS_POPUP, $WS_EX_TOPMOST)
    GUISetBkColor(0xFF0000) ; red

    GUIRegisterMsg($WM_MOVE, "WM_MOVE")

    GUISetState(@SW_SHOW, $g_hGUI)
    GUISetState(@SW_SHOW, $g_hGUI2)

    While 1
        Switch GUIGetMsg()
            Case $GUI_EVENT_CLOSE, $idButton_Close
                ExitLoop

            Case $idButton_1
                MsgBox($MB_TOPMOST, "Title", "Button_1 pressed")
        EndSwitch
    WEnd

    GUIDelete($g_hGUI2)
    GUIDelete($g_hGUI)
EndFunc   ;==>Example

;===========================================
Func WM_MOVE($hWnd, $iMsg, $wParam, $lParam)

    If $hWnd = $g_hGUI Then
        Local $aPos = WinGetPos($g_hGUI)
        WinMove($g_hGUI2, "", $apos[0], $apos[1])
    EndIf

    Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_MOVE

Edit: that's just a start.
Maybe the WinApi functions dealing with z-order could be used in the loop to have $g_hGUI2 stick to $g_hGUI1 when there is a new active window, maybe... :D

Edited by pixelsearch
Link to post
Share on other sites

Hi Pixelsearch,

I tested it a bit on the real Picasa window. As I need to display the GUI menu and a custom title bar (sorry I didn't mention it!), I excluded $WS_POPUP as an option, as it shows only the menu without the title bar (although it's interesting to see how to get a menu alone; thanks for the tip!).

Moreover, I excluded the $WS_EX_TOPMOST as it forces the menu on top of all other non topmost windows (which I want to avoid in the first place).

At the end, experimenting various combinations, one of the simplest seems to work as required, avoiding covering the top part of other apps, but including the "will-not-move-on-mouse-drag", "do-not-appear" in the Alt+Tab sequence and "stay-on-top-of-Picasa-window":

$hGUI_Arch_menu = GUICreate($menuname, $apos[2], 20, $aPos[0]+3, $apos[1]+3, -1, -1, $hwndPicasa)

So it works, except one detail: I need to disable the minimize button in the GUI menu title bar so the menu never minimizes (the close button already doesn't do anything, and the maximize button appears disabled). 

I tried some attempts with various styles and ex-styles but unfortunately some of them break also the basic requirements, achieved by the -1 defaults.

Therefore the question: how can I get rid of the minimize button, keeping the rest? I read the related help more than once but it looks like the solution escapes to my brain... ehm...forumupload.thumb.jpg.9469db38f3815e0aec3dcab333330f26.jpg 

Thanks a million, with kindest regards,

Bruno

 

Link to post
Share on other sites

A couple of lines to add if you want also to grey the X button (you still can close the GUI by keying Escape)

#include <GUIMenu.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>

Local $hGUI = GUICreate("No mini, No maxi, No red X", 400, 200, -1, -1, _
   BitXOR($GUI_SS_DEFAULT_GUI, $WS_MINIMIZEBOX)) ; mini 0, Maxi 0, red X 1

Local $hMenu = _GUICtrlMenu_GetSystemMenu($hGUI)
_GUICtrlMenu_EnableMenuItem($hMenu, $SC_CLOSE, $MF_GRAYED, False) ; red X 0

GUISetState()

Do
Until GUIGetMsg() = $GUI_EVENT_CLOSE

GuiDelete($hGUI)

 

Link to post
Share on other sites

Thanks, thanks, thanks!

Both work as a charm!

So the BitXOR is removing items... I guess I should know it already, but also my brain is removing items that has troubles with 😞. And I had no clue that one can disable not only the menu items but also the icons... wow!

Kindest regards

Bruno

Link to post
Share on other sites

Bruno,
As you don't need any of the 3 buttons (minimize, maximize, close), then you could use a GUI style = 0

For example, if you run the GUICtrlCreateMenu example from the help file, you could do this by changing this line...

GUICreate("My GUI menu", 300, 200)

...to that one

GUICreate("My GUI menu", 300, 200, -1, -1, 0) ; Style 0 = $WS_OVERLAPPED (also named $WS_TILED)


209172669_GUIwithout3buttons.png.7f0491f84969a4254d8fec50f4aa0d61.png

Link to post
Share on other sites

Hi everybody :)
It was an interesting challenge to study OP's questions. Here are my final results in 2 nearly similar scripts.

1) First script just to play with, using a GUI (popup style) to cover constantly the upper left corner of a non-AutoIt application. The application can be maximized, minimized, restored, resized or moved. Important variables are :

* $hWnd    = handle of the non-AutoIt application. It may be Picasa, a Browser, NotePad, whatever...
* $g_hGUI  = handle of the GUI that will cover the upper left corner of $hWnd
* $hAbove = handle of the window placed just above $hWnd in the z-order list
 

#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <WinAPISysWin.au3>

Global $g_hGUI ; as in future script (with menu) which will register a message

Example()

Func Example()
    Local $hWnd, $hAbove, $sWndTitle = " I'm  Picasa Window"

    If WinExists($sWndTitle) Then
        $hWnd = WinGetHandle($sWndTitle)
        WinActivate($hWnd)
    Else
        Run("notepad.exe")
        $hWnd = WinWait("[CLASS:Notepad]", "", 10)
        WinSetTitle($hWnd, "", $sWndTitle)
    EndIf

    Local $aPos_Old = WinGetPos($hWnd), $aPos_New

    $g_hGUI = GUICreate("Covering PopUp", 50, 50, $aPos_Old[0] + 2, $aPos_Old[1] + 2, $WS_POPUP)
    GUISetBkColor(0xFF0000) ; red

    GUISetState()

    While 1
        If GUIGetMsg() = $GUI_EVENT_CLOSE Or Not WinExists($hWnd) Then ExitLoop ; Esc key leaves too

        $aPos_New = WinGetPos($hWnd)
        If $aPos_Old[0] <> $aPos_New[0] Or $aPos_Old[1] <> $aPos_New[1] Then
            WinMove($g_hGUI, "", $aPos_New[0] + 2, $aPos_New[1] + 2)
            $aPos_Old = $aPos_New
        EndIf

        $hAbove = _WinAPI_GetWindow($hWnd, $GW_HWNDPREV) ; which window is just above $hWnd in z-order ?
        If $g_hGUI <> $hAbove Then ; if it's not $g_hGUI then force $g_hGUI to be just above $hWnd in z-order
            _WinAPI_SetWindowPos($g_hGUI, $hAbove, 0, 0, 0, 0, BitOr($SWP_NOMOVE, $SWP_NOSIZE))
        EndIf
    WEnd

    GUIDelete($g_hGUI)
    If WinExists($hWnd) Then WinClose($hWnd)
EndFunc   ;==>Example

2) Second script, with $g_hGUI corresponding to a GUI without any style, but including a menu which covers constantly the menu of the non-AutoIt application (OP's need). Of course, adjusting GUI coords (width & height) will depend on the application :

#include <GUIConstantsEx.au3>
#include <MenuConstants.au3>
#include <MsgBoxConstants.au3>
#include <WindowsConstants.au3>
#include <WinAPISysWin.au3>

Global $g_hGUI

Example()

Func Example()
    Local $hWnd, $hAbove, $sWndTitle = "Here we have an endless title: this is Picasa Window"

    If WinExists($sWndTitle) Then
        $hWnd = WinGetHandle($sWndTitle)
        WinActivate($hWnd)
    Else
        Run("notepad.exe")
        $hWnd = WinWait("[CLASS:Notepad]", "", 10)
        WinSetTitle($hWnd, "", $sWndTitle)
    EndIf

    Local $aPos_Old = WinGetPos($hWnd), $aPos_New

    ;========
    $g_hGUI = GUICreate("Covering Menu", 250, 50, $aPos_Old[0] + 2, $aPos_Old[1] + 2, 0) ; 0 = $WS_OVERLAPPED

    Local $idFilemenu = GUICtrlCreateMenu("&File")
    Local $idFileitem = GUICtrlCreateMenuItem("Open", $idFilemenu)
    GUICtrlSetState(-1, $GUI_DEFBUTTON)
    Local $idRecentfilesmenu = GUICtrlCreateMenu("Recent Files", $idFilemenu)
    GUICtrlCreateMenuItem("", $idFilemenu)
    GUICtrlCreateMenuItem("Save", $idFilemenu)
    GUICtrlSetState(-1, $GUI_DISABLE)
    Local $idExititem = GUICtrlCreateMenuItem("Exit", $idFilemenu)

    Local $idHelpmenu = GUICtrlCreateMenu("?")
    Local $idInfoitem = GUICtrlCreateMenuItem("Info", $idHelpmenu)
    ;========

    GUIRegisterMsg($WM_SYSCOMMAND, "WM_SYSCOMMAND")

    GUISetState()

    Local $sFile
    While 1
        Switch GUIGetMsg()
            Case $GUI_EVENT_CLOSE, $idExititem ; Esc key leaves too (no X button in this covering GUI)
                ExitLoop
            Case $idFileitem
                WinSetState($hWnd, "", @SW_DISABLE)
                $sFile = FileOpenDialog("Choose file...", @TempDir, "All (*.*)", 0, "", $g_hGUI)
                If @error <> 1 Then GUICtrlCreateMenuItem($sFile, $idRecentfilesmenu)
                WinSetState($hWnd, "", @SW_ENABLE)
            Case $idInfoitem
                WinSetState($hWnd, "", @SW_DISABLE)
                MsgBox($MB_TOPMOST, "Info", "Only a test...", 0, $g_hGUI)
                WinSetState($hWnd, "", @SW_ENABLE)
        EndSwitch

        If Not WinExists($hWnd) Then ExitLoop ; user closed Picasa window

        $aPos_New = WinGetPos($hWnd)
        If $aPos_Old[0] <> $aPos_New[0] Or $aPos_Old[1] <> $aPos_New[1] Then
            WinMove($g_hGUI, "", $aPos_New[0] + 2, $aPos_New[1] + 2)
            $aPos_Old = $aPos_New
        EndIf

        $hAbove = _WinAPI_GetWindow($hWnd, $GW_HWNDPREV) ; which window is just above $hWnd in z-order ?
        If $g_hGUI <> $hAbove Then ; if it's not $g_hGUI then force $g_hGUI to be just above $hWnd in z-order
            _WinAPI_SetWindowPos($g_hGUI, $hAbove, 0, 0, 0, 0, BitOr($SWP_NOMOVE, $SWP_NOSIZE))
        EndIf
    WEnd

    GUIDelete($g_hGUI)
    If WinExists($hWnd) Then WinClose($hWnd)
EndFunc   ;==>Example

;================================================
Func WM_SYSCOMMAND($hWnd, $iMsg, $wParam, $lParam)

    ; msdn: in WM_SYSCOMMAND messages, the four low-order bits of the wParam parameter are used internally by the system.
    ; To obtain the correct result when testing the value of wParam, an application must combine the value 0xFFF0 with
    ; the wParam value by using the bitwise AND operator.
    If $hWnd = $g_hGUI And BitAND($wParam, 0xFFF0) = $SC_MOVE Then Return False

    Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_SYSCOMMAND

455945385_Coveringmenu.png.99cd82e68b5556fdbf688b07430c6403.png

If you guys find a bug or think about some improvements, please share your thoughts here.

Link to post
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
  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...