Jump to content

WM_Paint message (involves dllcall)


Recommended Posts

Okay, so I'm trying to create my own GUI ctrl and have default AutoIt ctrls on the same window. However, I've had this problem with my code that's been bugging me for a few months. Most of the time it seems to work, but every now and then it doesn't seem to refresh properly and all of the AutoIt ctrls disappear. I've been using GUIRegisterMsg on WM_Paint to get my code to work. One weird thing that I noticed is that even if my function returns nothing, which should stop the internal handler, the AutoIt ctrls are still being drawn, and if I put a sleep statement at the beginning of the code, the AutoIt ctrls are drawn, but my ctrls aren't. This leads me to believe that instead of handling my code and then doing the internal handler, AutoIt seems to be doing them at the same time. Anyone have any ideas?

P.S. -When the AutoIt ctrls disappear, I minimize and maximize the window and that fixes it beautifully. I don't know if that information gives you guys any ideas.

By the way, the problem seems to be with BeginPaint/EndPaint. If I don't use those, it seems to work pretty well, but I run into other issues then.

-Thanks

Michael

Redraw code:

GUIRegisterMsg(0x000F, "TGF_Private_Refresh")

Func TGF_Private_Refresh($hWndGUI, $MsgID, $wParam, $lParam)
    ;obtain the in-memory picture that I then bitblt to the window(TGF_Private_InRow is at another location in my program)
    Local $infoRow = TGF_Private_InRow($hWndGUI)  

    Local $paint = DllStructCreate("int;int;long;long;long;long;int;int;byte[32]")
    Local $deviceContext = DllCall("user32.dll", "int", "BeginPaint", "hwnd", $hWndGUI, "ptr", _ 
      DllStructGetPtr($paint))

    ;bitblt the in-memory picture to the window($TGF_WindowLog is a global variable in my program that contains the in-memory picture)
    Local $work = DllCall("gdi32.dll", "int", "BitBlt", "int", $deviceContext[0], "int", DllStructGetData($paint, 3), "int", DllStructGetData($paint, 4), "int", _ 
      DllStructGetData($paint, 5) - DllStructGetData($paint, 3), "int", DllStructGetData($paint, 6) - DllStructGetData($paint, 4), "int", $TGF_WindowLog[$infoRow][1], "int", DllStructGetData($paint, 3), "int", _
      DllStructGetData($paint, 4), "int", 0xcc0020)
 
    DllCall("user32.dll", "int", "EndPaint", "hwnd", $hWndGUI, "ptr", DllStructGetPtr($paint))
    $paint = 0
    Return $GUI_RUNDEFMSG
EndFunc
Edited by tobias7
Link to comment
Share on other sites

I have different philosophy in my WM_PAINT where I draw red cros over picture control:

...
GUIRegisterMsg($WM_PAINT, "MY_WM_PAINT")
...

Func MY_WM_PAINT($hWnd, $Msg, $wParam, $lParam)
    RedrawWindow($pic_hWnd, 0, 0, $RDW_UPDATENOW) ; force redraw of pic
    MalujKriz() ; then draw my stuff on top
    RedrawWindow($pic_hWnd, 0, 0, $RDW_VALIDATE) ; then force no-redraw of pic
    Return $GUI_RUNDEFMSG
EndFunc

Func RedrawWindow($hWnd, $tRect = 0, $hRegion = 0, $iFlags = 5)
    Local $pRect, $aResult

    If $tRect <> 0 Then $pRect = DllStructGetPtr($tRect)
    $aResult = DllCall("User32.dll", "int", "RedrawWindow", "hwnd", $hWnd, "ptr", $pRect, "int", $hRegion, "int", $iFlags)
    Return ($aResult[0] <> 0)
EndFunc


Func MalujKriz() ; vzdy po zmene obrazku
    If $ZobrazitKriz = 0 Then Return
    If $pocet = 0 Then Return
    If $kriz[0] = 1 Then Return
        $x = $kriz[2]*$velikost
    $y = $kriz[3]*$velikost
    $pen = DLLCall($gdi_dll,"int","CreatePen","int",0,"int",$velikost,"int",0xFF)
    $obj_orig = DLLCall($gdi_dll,"int","SelectObject","int",$pic_hdc,"int",$pen[0])
    DLLCall($gdi_dll,"int","MoveToEx","int",$pic_hdc,"int",$x,"int",$y-10*$velikost,"int",0)
    DLLCall($gdi_dll,"int","LineTo","int",$pic_hdc,"int",$x,"int",$y+11*$velikost) ;vertical line
    DLLCall($gdi_dll,"int","MoveToEx","int",$pic_hdc,"int",$x-10*$velikost,"int",$y,"int",0)
    DLLCall($gdi_dll,"int","LineTo","int",$pic_hdc,"int",$x+11*$velikost,"int",$y) ;horizontal line
    DLLCall($gdi_dll,"int","SelectObject","int",$pic_hdc,"int",$obj_orig[0])
    DLLCall($gdi_dll,"int","DeleteObject","int",$pen[0])
EndFunc

This is related code snippet from my Radar project.

You may look at older version in my signature.

Also post TGF_Private_InRow() source ...

Link to comment
Share on other sites

I fixed it! Zedna was right about not bothering to use BeginPaint and EndPaint. I think those functions are used by AutoIt when WM_PAINT is called even if you return nothing, and it creates conflicts if you use them again. Instead I used GetDC to get the device context, and other information to know where to bitblt. The problem I mentioned before was that instead of using GetDC, I was using GetWindowDC (or something similar), and when I painted, it would paint over the windows' title bar. I am so glad to finally have that bug fixed!!!

Link to comment
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
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...