Move a clarion window from clicking on a region

This is something I have used in the ClarionMetroWizard project to move allow you to move a window that doesn’t have a title bar.

NOTE: Look here for a more correct implementation - http://support.microsoft.com/kb/114593
Edit: https://www.betaarchive.com/wiki/index.php/Microsoft_KB_Archive/114593

The below code works well enough but it does have some limitations, such as the nested ACCEPT loop will stop the calling window from receiving events.

MoveWindow PROCEDURE()
origX LONG
origY LONG
CODE
 
  CASE Field()
  OF ?MyRegion
    CASE EVENT()
    OF Event:MouseDown
      origX = MOUSEX()
      origY = MOUSEY()
      ACCEPT
        CASE EVENT()
        OF Event:MouseUp
          BREAK
        OF Event:MouseMove
          0{Prop:Xpos} = 0{Prop:Xpos} + (MOUSEX() - origX)
          0{Prop:Ypos} = 0{Prop:Ypos} + (MOUSEY() - origY)
        END
      END
    END
  END

Original Gist: https://gist.github.com/fushnisoft/4f9da267e165033e007a

Found in the Clarion help:

Proposed improvement:

SETPOSITION(0, 0{Prop:Xpos} + (MOUSEX() - origX), 0{Prop:Ypos} + (MOUSEY() - origY))
1 Like
1 Like

I’ll post the code here to make it easier to discuss. Best to get it from the GIST

AboutWindow WINDOW,AT(,,270,120),CENTER,GRAY,FONT('Segoe UI',10),COLOR(COLOR:White),DOUBLE
        STRING('About Window'),AT(70,20),FONT(,24,,FONT:bold)
        STRING('Drag Me'),AT(103,77),FONT(,16,,FONT:regular)
        BUTTON('X'),AT(258,0,11,9),USE(?Xclose),SKIP,STD(STD:Close)
        REGION,AT(1,1),FULL,USE(?MoveRegion),IMM
    END
RgIsMoving  BOOL        
RgMsOrigX   LONG        
RgMsOrigY   LONG        
RgWinOrigX  LONG        
RgWinOrigY  LONG        
RgMsPrevX   LONG
RgMsPrevY   LONG        
MX          LONG        
MY          LONG          
  CODE
  OPEN(AboutWindow)
  ACCEPT
    CASE FIELD()
    OF ?MoveRegion
      CASE EVENT()
      OF EVENT:MouseDown
         RgIsMoving = 1       
         RgMsOrigX = MOUSEX() ; RgMsPrevX = RgMsOrigX  
         RgMsOrigY = MOUSEY() ; RgMsPrevY = RgMsOrigY  
         GETPOSITION(0,RgWinOrigX,RgWinOrigY)
      
      OF EVENT:MouseUP
         RgIsMoving=0
      
      OF EVENT:MouseMove
         IF RgIsMoving THEN
              MX=MOUSEX()
              MY=MOUSEY()
              IF ABS(MX-RgMsPrevX)>3 OR ABS(MY-RgMsPrevY)>3 THEN    !move a little less
                  RgWinOrigX=RgWinOrigX+(MX-RgMsOrigX)
                  RgWinOrigY=RgWinOrigY+(MY-RgMsOrigY)
                  SETPOSITION(0,RgWinOrigX, RgWinOrigY)
                  RgMsPrevX=mouseX()    !must store Prev After moving window because that changes the relative mouse value
                  RgMsPrevY=mouseY()
              END
          END !If Is Move
      END !Case Event  
    END 
  END
1 Like

I can’t recommend this approach in serious projects, it really works bad.

Hi Mike!

Bad in what way?
There are certainly things to be aware of, such as thread blocking, but can you point to anything more specific?

Hi Brahn,
A window moving is not smooth, especially if you move it too quick and in different directions.

My code is smooth for big moves in my tests, it does have some jitter with small moves because I was trying to not make small moves i.e. < 4. Not sure why I was doing that, the code was on a window with many controls though all simple. I would call it serious running on 20,000+ systems. It had the Check for Update button. I used it via remote many times and moved the window many times because it was centered over my 2 monitors.

I added Brahn’s code to my program and updated my GIST. I find it works smooth (no jitter compared to mine) and is much simpler. Run my GIST code and you get 5 versions up at once. The last one I like best is Brahn’s using GETPOSITION and the nested ACCEPT is replaced with a BOOL; otherwise, seems like events could be lost (swallowed by the nested accept) and also this is simpler code:

BrahnMove1Accept PROCEDURE()
AboutWindow WINDOW,AT(,,270,120),CENTER,FONT('Segoe UI',10),COLOR(0E1FFFFH),DOUBLE
        STRING('Click n Drag Me'),AT(97,77),USE(?DragMe),FONT(,16,,FONT:regular)
        STRING('Mouse'),AT(97,97),USE(?MouseXY),FONT(,12,,FONT:regular)
        REGION,AT(1,1),FULL,USE(?MoveRegion),IMM
    END
MsDownX LONG,AUTO 
MsDownY LONG,AUTO 
WndX    LONG,AUTO 
WndY    LONG,AUTO
MouseIsDown BOOL   !Event:MouseDown occured in Region so Move Window 
  CODE
  OPEN(AboutWindow)
  ACCEPT
     CASE FIELD()
     OF ?MoveRegion
         CASE EVENT()
         OF Event:MouseDown
           MsDownX = MOUSEX()
           MsDownY = MOUSEY()
           MouseIsDown = 1   ; ?DragMe{PROP:Text}='Mouse Down Drag'  

         OF Event:MouseUp
            MouseIsDown=0    ; ?DragMe{PROP:Text}='Mouse Up' 

         OF Event:MouseMove  
            IF MouseIsDown THEN 
               GETPOSITION(0,WndX, WndY)
               SETPOSITION(0,WndX + (MOUSEX() - MsDownX), WndY + (MOUSEY() - MsDownY))
            END  
            !Show MouseMove in Region with IMM. Get event for any Mouse Over with IMM
            ?MouseXY{PROP:Text}='Event:MouseMove ' & MOUSEX() &','& MOUSEY()

         END !Case Event 
      END    !Case Field
  END
1 Like

Thanks Carl and Brahn. I’ve used “Brahn’s original” as my method for many years.

Would it help to switch to prop:pixels = true

There’s no problem in my testing, it moves smooth enough for me… perfect.

I’m surprised it works as well as it does. The MouseX/Y is relative to the Window. In Event:MouseMove the Window is moved by the X/Y change in the mouse. So after the mouse is at its original X/Y relative to the new Window X/Y …. I think that’s it, yeah, yeah that’s the ticket.

Pixels might be better as higher resolution. I tried it and I would say it seemed smoother. I set Pixels=1 in MouseDown and =0 in Mouse Up. I suppose there’s some possibility of Event:Move code executing not expecting Pixels=1.

8/21 … I changed my GIST to have a CHECK(‘Use Pixels’) so it can be tried easily. I don’t see a need. Niether SETPOSITION nor PROP:Xpos= generate an EVENT:Move so seems safe to leave Pixels=1 during drag.

I just noticed the link in my original post was broken. Archive link in its place but I’m not sure how long that will last https://www.betaarchive.com/wiki/index.php/Microsoft_KB_Archive/114593

Subclassing the window and something something should be able to achieve the same result and also not lock the thread right? Should also result in a smoother ui.