Jump to content


Drag for Static Control - Continuation


  • Please log in to reply
20 replies to this topic

#1 Trente

Trente
  • Guests

Posted 28 May 2010 - 01:59 PM

Continued from http://www.autohotke...264.html#358264




not possible to do a true drag vs click


I did not tell that. I do not know your application.
Mine is Picture Puzzle where I use 'drag control' to swap picture tiles.
Try the following:



That did the trick quite nicely, thanks!


Honestly, I am pleased when somebody finds 'help' in my post. Most of my replies in Ask-for-help do not attract a reply from the original poster. :(



Well, you won't get that kind of ingratitude from me. :)


Incidentally, I'm still encountering visual glitches, even with the additional Redraw.

I'm using PNG's with transparency, and if I stack several of them with partial overlaps (like the way you'd fan a hand of cards), then grab another one and pass it over the whole stack left or right - after a few passes, there start to be problems.

Sometimes it's that the second image from the top all of a sudden becomes the top image. Or we can get all kinds of visual "jump through".

I tried "dllCall("UpdateWindow", UInt, sHwnd1)", as TLM suggested, but it didn't seem to make a difference.

#2 Trente

Trente
  • Guests

Posted 28 May 2010 - 02:21 PM

Just for some clarification, you can more easily see glitches if you drag an image on top of the fanned stack, let the mouse go. Then drag the same image left or right.

Try that a few times, and you'll quickly see some issues. Sometimes, you end up dragging one of the images that was behind the one on top, so it's as if the images actually change order, not just look like it.

#3 SKAN

SKAN
  • Administrators
  • 9062 posts

Posted 29 May 2010 - 01:04 PM

Sample code and few png-transparent-images would help. You can upload images at <!-- w -->www.autohotkey.net<!-- w -->

#4 Trente

Trente
  • Guests

Posted 29 May 2010 - 04:03 PM

Sample code and few png-transparent-images would help. You can upload images at www.autohotkey.net



You can grab what you need here:

http://drop.io/hidde...as ... 16aXA%3D



Also, this graphics glitch isn't limited to transparency PNG's. The PNG's I included have no transparency. In addition, I tested the issue with JPG's, and it occurs there as well.

I already set the images up to come up in a fanned stack. Just grab any image, drag it anywhere on top of the stack, let go, and drag it again. Play around like that, and you'll see the magic happen pretty quickly. You'll even end up grabbing images that were supposed to be behind the one you dropped on top.


And just for kicks, I used this script along with the *second* one here:
http://www.autohotke...997.html#167997

...which produces a tiled background. I can't reproduce it at will, but relatively frequently, when I try to drag an image using your script on top of that tiled background, I find myself dragging the tiled background instead. That was a surprise, I can tell you. Especially since the tiled background does NOT attach to your script code.

Just keep grabbing images at random, dragging them left and right, dragging other ones - within about 30-60 seconds, you should encounter that background grab.


I don't know if that's related to these other issues or not - but since the current issues include dragging an image that's supposed to be behind the one you're grabbing, I thought it might be relevant.

#5 SKAN

SKAN
  • Administrators
  • 9062 posts

Posted 29 May 2010 - 04:12 PM

You can grab what you need here:

<!-- m -->http://drop.io/hidde...as ... 16aXA%3D<!-- m -->


The link does not work for me. I do not know your application. I need sample code along with pictures to reproduce the said effect.

Edit. Okay! It is working now. I will check it out.

#6 Trente

Trente
  • Guests

Posted 01 June 2010 - 01:26 AM

I just noticed another issue, which overlaps the other bugs.

For click actions, when clicking on any set of fan stacked images, the bottom-most image is the one that registers the click, no matter how deep the stack.

So if you have three images fan stacked, and you click on the topmost image, but where it overlaps the bottom-most image, the bottom-most image will be what A_GuiControl is set to.

#7 JimmyG

JimmyG
  • Guests

Posted 03 June 2010 - 06:06 PM

Confirmed. I saw both the visual glitches as well as the bug of the bottom-most image being the one registering the click. That appears to be a general AHK bug, as opposed to something related to this script.

The question is whether or not there is a currently useable fix/workaround. I have no idea.

Some of the other experts need to chime in on this, because this is a pretty serious bug, as far as GUI's are concerned.

#8 Trente

Trente
  • Guests

Posted 04 June 2010 - 01:55 PM

Good point. I just posted some of this in the Bugs sub, to register it.

#9 Trente

Trente
  • Guests

Posted 08 June 2010 - 03:10 PM

SKAN, did you ever make any headway seeing if there was a way around these issues?

#10 SKAN

SKAN
  • Administrators
  • 9062 posts

Posted 08 June 2010 - 03:36 PM

SKAN, did you ever make any headway seeing if there was a way around these issues?


I did look into it..

If you add 0x4000000 ( WS_CLIPSIBLINGS ) in every picture's 'options', all visual artifacts are avoided.

SC_MOVE message alters the z-order of the controls. When multiple controls share the same WindowPoint ( parent window coordinate ), MouseGetPos retrieves the hwnd of the control highest in the z-order. Part of the problem is, the highest control in z-order need not neccessarily be the foremost visible control. The other part of the problem is to learn how MouseGetPos treats when clicking through the transparent area of the foremost visible control. I think I will have to experiment with [Real]ChildWindowFromPoint() in lieu of MouseGetPos.

One way to control the z-order of controls is to call SetWindowPos(), but I did not get it right when I last tried it. I have the feeling that I am just few steps away from the solution, but since I have been involved in an another project, I have been postponing my experiment.

Anyways.. here is what I have so far:

<!-- m -->http://dl.dropbox.co...ragControls.zip<!-- m -->

#11 Trente

Trente
  • Guests

Posted 09 June 2010 - 05:13 AM

I appreciate the time and effort you're putting into this, believe me!

I was glad to see that WS_CLIPSIBLINGS eliminates the visual artifacts. I noticed, however, that doing that wasn't compatible with that tiled background. I think all the images that had WS_CLIPSIBLINGS as part of its options were showing up *behind* the tiled background, and so wasn't visible unless I disabled that background.

As for SC_MOVE and MouseGetPos, I noticed that if you just load a bunch of fan stacked images, with no drag code whatsoever, but simply a MsgBox that shows you A_GuiControl of what was clicked, it always registers the bottom-most image.

In any case, thank you for continuing to look into this - I'll continue to experiment as well.

To be honest, I would have thought the behavior we're looking for would be naturally supported by AHK, and not require the kind of code maneuvering this is turning out to require. :)

#12 SKAN

SKAN
  • Administrators
  • 9062 posts

Posted 09 June 2010 - 05:53 AM

As for SC_MOVE and MouseGetPos, I noticed that if you just load a bunch of fan stacked images, with no drag code whatsoever, but simply a MsgBox that shows you A_GuiControl of what was clicked, it always registers the bottom-most image.



Confusing Z ordering

<!-- m -->http://webcache.goog... ... -1600.html<!-- m -->


Keywords: SetWindowPos, GetWindow, GW_HWNDNEXT, GW_HWNDPREV, hWndInsertAfter, Z order

Like the previous item, this is a clarification issue. The documentation is not wrong - it's just a bit obtuse in places.

Windows stores Z-order information in a counter-intuitive way. At least to me, with my background of graphics applications, items in a Z-ordered list are stored lowest item first, highest item last. Windows does not do this - in a list of sibling windows, the first window is the one at the top of the Z-order.

For example, here is a screen grab from Microsoft Spy++, looking at the dialog of one of my applications:


Note
The easiest way I have found to think about this is that when you look at a tree display of your window hierarchy in Spy++, then that is a correct spatial representation of the Z-order - i.e. in the screen grab to the left, the higher up a window is, the higher it is in the Z-order.
For example, window 000E0B7A is above the window 000D0B62 in the screenshot, which means it is also above window 000D0B62 in the Z-order. This is about the only scenario where this ordering makes sense.

This dialog contains a tab control, and two child dialogs that are used to display the controls on each tab (they're the last 3 items in the list). The dialogs need to be in front of the tab control - and they are. You can see from the picture that the tab control is last in the list, which means it is at the bottom of the Z-order. The two child dialogs are before the tab control in the list, which means they are above the tab control in the Z-order.

That is a bit confusing, but it gets really confusing with window relationships, as in calls to GetWindow(). To get the window above/below the window you are interested in, you use the constants GW_HWNDPREV and GW_HWNDNEXT. Using GW_HWNDPREV gets you the window before the specified window, which is actually above the specified window. Similarly, GW_HWNDNEXT gets you the next window, which is actually below the specified window.

The problem is compounded with the hWndInsertAfter parameter of the SetWindowPos() function. It is documented as follows:

hWndInsertAfter

Handle to the window to precede the positioned window in the Z order.

So when you call SetWindowPos(), your window will actually be positioned below or behind the window specified in hWndInsertAfter. Again, this seems to me to be counter-intuitive. Similarly, when Windows has to draw the windows using the painter's algorithm, it has to traverse the list in reverse order.

You may be thinking "What's the problem? It makes perfect sense!" - in which case, lucky old you. The rest of us have to try to cope with the slightly counter-intuitive terminology.



#13 SKAN

SKAN
  • Administrators
  • 9062 posts

Posted 10 June 2010 - 08:56 PM

Try this, Trente

IfNotExist, *.png
  Loop 5
   UrlDownloadtoFile, http://www.autohotkey.net/~goyyah/pic%A_Index%.png, pic%A_Index%.png
Loop *.png
   Gui, 1:Add, Picture, xp+64 y32 hwndhWnd%A_Index% Border vI%A_Index% gControlMove
                       +0x4000000, %A_LoopFileLongPath%   ; WS_CLIPSIBLINGS := 0x4000000
Gui, 1:Show, w800 h600, Draggable-Controls
Return
ControlMove:
  Ix := SubStr( A_GuiControl,2 ), sHwnd := hWnd%Ix%
  DllCall( "SetWindowPos", UInt,sHwnd, UInt,0, UInt,0, UInt,0, UInt,0, UInt,0, UInt,0x43 )
  Sleep -1     ; ^ SWP_NOMOVE := 0x2 | SWP_NOSIZE := 0x1 | SWP_SHOWWINDOW := 0x40 = 0x43
  SendMessage, 0x112, 0xF012, 0,, ahk_id %sHwnd%             ; WM_SYSCOMMAND and SC_MOVE
Return


#14 Trente

Trente
  • Guests

Posted 11 June 2010 - 08:05 PM

Incredible! I just gave it a quick look so far, but at a first glance, that works beautifully!

Quick question, though - when using this code with the function to provide a tiled background, the images from this script are still loading behind the tiled background. In fact, they're draggable *through* the tiled background - meaning that the outline of the image shows up and is draggable, but you can't see the actual image, instead you've broken away part of the tiled background.

Does the tiling function need to be updated to work with this? Or is it something that needs to be tweaked with this code?

#15 SKAN

SKAN
  • Administrators
  • 9062 posts

Posted 11 June 2010 - 08:32 PM

Does the tiling function need to be updated to work with this? Or is it something that needs to be tweaked with this code?


The Tiling function should called after you load your images. Also set WS_CLIPSIBLINGS for the 'Tiled Background'.

Like:

Gui, +Resize

xcoord := 10
Loop 7
{
   Gui, 1:Add, Picture, x%xcoord% y25 hwndhWnd%A_Index% vI%A_Index% gControlMove
                       [color=red]+0x400000[/color]0, %A_Index%.png   ; WS_CLIPSIBLINGS := 0x4000000
   xcoord += 200
}

Gui, 1:Add, Pic, x0 y0 w157 h157 +0x4000000 hwndTiledPic, %A_WorkingDir%\grey.jpg
TileImage( TiledPic,157,157 )
Gui, Show, Maximize
Return

ControlMove:
  Ix := SubStr( A_GuiControl,2 ), sHwnd := hWnd%Ix%
  DllCall( "SetWindowPos", UInt,sHwnd, UInt,0, UInt,0, UInt,0, UInt,0, UInt,0, UInt,0x43 )
  Sleep -1     ; ^ SWP_NOMOVE := 0x2 | SWP_NOSIZE := 0x1 | SWP_SHOWWINDOW := 0x40 = 0x43
  SendMessage, 0x112, 0xF012, 0,, ahk_id %sHwnd%             ; WM_SYSCOMMAND and SC_MOVE
Return

; Copy / Paste TileImage()