2

I want to be able to drag my semi-transparent application window around the screen and "drop" it onto whichever window is under the pointer when I let go. At this point I want my GUI window to reconfigure itself to be congruent with the target window. It would also be nice to cause the target window to come out from behind all windows except mine.

Well, finally, I have some code to share. It works, mostly, but it doesn't always grab the entire target window. Sometimes it grabs only a portion of it. If you have any ideas, lay them on me, please. To activate a grab, I drag my window somewhere over the target, move the mouse pointer anywhere in the region where they overlap, and type "w." Type "w" again to restore my window to its previous state. It took me a long time to figure this out because I am a rank beginner. In the end the resolution turned to be surprisingly straightforward, I think. But, I would appreciate any help to streamline the code. It has a kludgy feel to it. Thanks in advance.

    if (e.key() == Qt.Key_W):
        if (self.makeBaby):
            self.makeBaby = False
            self.setGeometry(self.previousGeometry)
            self.updateStuff()      #> Redraw everything after getting    <#
                                    #> off her. How do you know it's a    <#
                                    #> girl? Her mouth is open.           <#
        else:
            self.makeBaby = True
            Joe = self.geometry()
            self.previousGeometry = Joe
            self.windowHandle = win32gui.WindowFromPoint((QCursor.pos().x(), QCursor.pos().y()))
                                    #> Get my window's handle.            <#
            self.move(self.ws, self.hs)
                                    #> Get out of the way.                <#
            windowHandle = win32gui.WindowFromPoint((QCursor.pos().x(), QCursor.pos().y()))
                                    #> Get the target window's handle.    <#
            windowRect = win32gui.GetWindowRect(windowHandle)
                                    #> Get its geometry.                  <#

            x = windowRect[0]
            y = windowRect[1]
            w = windowRect[2] - x
            h = windowRect[3] - y
            self.move(Joe.x(), Joe.y())
                                    #> Return to the playing field.       <#
            win32gui.SetWindowPos (windowHandle, self.windowHandle, x, y, w, h, win32con.SWP_NOSIZE|win32con.SWP_NOMOVE)
                                    #> Position the target window under   <#
                                    #> my window.                         <#
            self.raise_()           #> This and the next line are         <#
                                    #> necessary. I don't understand why. <#
            self.activateWindow()
            self.setGeometry(x, y, w, h)
                                    #> Match my window's geometry to the  <#
                                    #> target's.                          <#
            self.updateStuff()      #> Give her a new coat of paint.      <#
bloodbringer
  • 41
  • 1
  • 4
  • I tried "Code Review" but failed. It's too complicated for me. Confirm this. Verify that. Everything I tried was rejected, without explanation. Oh, well... I'm going back to dope school for a refresher course. – bloodbringer May 10 '18 at 01:21
  • OK, Edwin, today I'll try to perform a codectomy on the actual, complete, working program to produce a minimal version of same. Yes, I know this snippet is incomplete BUT I believe that this is the culprit. windowHandle = win32gui.WindowFromPoint((QCursor.pos().x(), QCursor.pos().y())) #> Get the target window's handle. <# – bloodbringer May 10 '18 at 13:55
  • I tried to enter a program but to no avail. Program exceeds 30000 characters. Oh, well. To Hell with it. – bloodbringer May 10 '18 at 23:51
  • I tried to answer to best of my understanding of your code... but I realize this may not be an answer at all, or only part of an answer. Good Luck ! – Edwin van Mierlo May 11 '18 at 11:53

1 Answers1

0

Let me try to give you some tips, based on your incomplete code. I understand you tried to upload more code to make it minimum verifiable, I understand that you hit some character limits, and gave up.

First of all, any code you write, including this one, will be read by others at some point in time. In this case you have uploaded your code to the internet, and is viewed by many. For this reason I believe you should keep your code comments professional.

While I might understand that your code comments are written with humor-tongue-in-cheek, I believe you should update comments, the following doesn't read very well, and might be insulting to some:

#> Redraw everything after getting    <#
#> off her. How do you know it's a    <#
#> girl? Her mouth is open.           <#

Back to your question, as I cannot reproduce the following is just based on reading your code.

You state:

it doesn't always grab the entire target window. Sometimes it grabs only a portion of it

First you get the position of your own window here, and move out of the way:

        self.windowHandle = win32gui.WindowFromPoint((QCursor.pos().x(), QCursor.pos().y()))
                                #> Get my window's handle.            <#
        self.move(self.ws, self.hs)
                                #> Get out of the way.                <#

While you are moving out of the way, you may consider to resize your own window to something ridiculously small. You do set the geometry of your own window later, so this can be done without loosing functionality of your code, example prior to moving you could set your own geometry like this:

self.setGeometry(1, 1, 1, 1)

This to ensure that your own window is not overlapping the target window.

Then you proceed to get the target window, here:

        windowHandle = win32gui.WindowFromPoint((QCursor.pos().x(), QCursor.pos().y()))
                                #> Get the target window's handle.    <#

You might consider bringing this window to the foreground before you gets the target-geometry. Bringing this window to the foreground is discussed here

When this target window is to the foreground, then proceed with getting its geometry, as your code shows:

        windowRect = win32gui.GetWindowRect(windowHandle)
                                #> Get its geometry.                  <#

Once you have that, you may want to debug with either print statements, or some file logging, to figure out if the returned windowRect is correct. Example:

        x = windowRect[0]
        y = windowRect[1]
        w = windowRect[2] - x
        h = windowRect[3] - y
        with open('somelog.txt', 'a') as logfile:
            logfile.write('x = {}\n'.format(str(x))
            logfile.write('y = {}\n'.format(str(y))
            logfile.write('w = {}\n'.format(str(w))
            logfile.write('h = {}\n'.format(str(h))
            logfile.flush()

This may help you debug the process if it "only grabs part of the target". You can use this type of logging in other parts of your program to figure out what is going on.

I am not sure if this is needed, experimentation may be needed:

        self.move(Joe.x(), Joe.y())
                                #> Return to the playing field.       <#

I am not clear about this one either, again you may have to look at this. This is where you position the target under yours, but would you not do the reverse? Position your window over the target, seems more logical. Do look if this is where your problem is:

        win32gui.SetWindowPos (windowHandle, self.windowHandle, x, y, w, h, win32con.SWP_NOSIZE|win32con.SWP_NOMOVE)
                                #> Position the target window under   <#
                                #> my window.                         <#

The rest of the code seems to be straight forward, again you may want to put some sort of logging in, when things still not go as you expect.

I apologize for the incomplete answer.

Edwin van Mierlo
  • 2,398
  • 1
  • 10
  • 19