_WinAPI_BitBlt Probleme

  • Hallo ich habe mir folgendes Skript gebastelt. Es soll eine "einfache" 2D GUI sein und es werden nur ein paar Elemente drauf gezeichnet. Nun will aber die FPS-Anzahl nicht über 16 steigen bei einem 3.6 GHz Prozessor. Kann vlt. noch jemand das Skript verbessern, außer mit OpenGL/CL.

    Spoiler anzeigen
    [autoit]

    #include <GDIPlus.au3>
    #include <GuiConstants.au3>
    #include <WindowsConstants.au3>
    #include <WinAPI.au3>

    [/autoit] [autoit][/autoit] [autoit]

    Opt("GUIOnEventMode",1)

    [/autoit] [autoit][/autoit] [autoit]

    _GDIPlus_Startup()

    [/autoit] [autoit][/autoit] [autoit]

    GUIRegisterMsg($WM_PAINT,"_Redraw")
    GUISetOnEvent($GUI_EVENT_CLOSE,"_Exit")

    [/autoit] [autoit][/autoit] [autoit]

    #region Brushes
    $bRed = _GDIPlus_BrushCreateSolid(0xFFFF0000)
    $bDarkRed = _GDIPlus_BrushCreateSolid(0xFF8B0000)
    $bBlue = _GDIPlus_BrushCreateSolid(0xFF0000FF)
    $bDarkBlue = _GDIPlus_BrushCreateSolid(0xFF00008B)
    $bGreen = _GDIPlus_BrushCreateSolid(0xFF00FF00)
    $bDarkGreen = _GDIPlus_BrushCreateSolid(0xFF008B00)
    $bDimGrey = _GDIPlus_BrushCreateSolid(0xFF696969)
    $bDarkGrey = _GDIPlus_BrushCreateSolid(0xFFA9A9A9)
    #endregion

    [/autoit] [autoit][/autoit] [autoit]

    Global $hWnd, $hDC_Window, $hDC_Bitmap, $hBitmap, $hGraphics, $hOldObj, $CPU_MIN = True; <= True bei über 2000 MHz, False bei weniger
    Global $BG = _GDIPlus_ImageLoadFromFile(""); Einfach ein Bild hier einfügen

    [/autoit] [autoit][/autoit] [autoit]

    $hGui_Main = GUICreate("MyGui",@DesktopWidth,@DesktopHeight,0,0,BitOR($WS_POPUP,$WS_MAXIMIZE))

    [/autoit] [autoit][/autoit] [autoit]

    $hDC_Window = _WinAPI_GetDC($hGui_Main)
    $hDC_Bitmap = _WinAPI_CreateCompatibleDC($hDC_Window)
    $hBitmap = _WinAPI_CreateCompatibleBitmap($hDC_Window, @DesktopWidth, @DesktopHeight)
    $hOldObj = _WinAPI_SelectObject($hDC_Bitmap, $hBitmap)

    [/autoit] [autoit][/autoit] [autoit]

    $hGraphic = _GDIPlus_GraphicsCreateFromHDC($hDC_Bitmap)
    _GDIPlus_GraphicsSetSmoothingMode($hGraphic, 2)

    [/autoit] [autoit][/autoit] [autoit]

    GUISetState(@SW_SHOW,$hGui_Main)

    [/autoit] [autoit][/autoit] [autoit]

    #region Variablen
    Global $SliderPerc = 0,$SliderX_New
    Global $SliderWidth = @DesktopWidth / 6
    Local $aTemp

    [/autoit] [autoit][/autoit] [autoit]

    $MouseDiffX = 0
    $SliderX = (@DesktopWidth / 7) + $MouseDiffX
    $SliderY = @DesktopHeight * 0.95

    [/autoit] [autoit][/autoit] [autoit]

    $SliderX_New = $SliderX

    [/autoit] [autoit][/autoit] [autoit]

    ;===============================;
    Dim $aMainButton1[7]
    $aMainButton1[0] = 0
    $aMainButton1[1] = @DesktopWidth / 2 - (@DesktopWidth / 10)
    $aMainButton1[2] = @DesktopHeight / 2 - (@DesktopWidth / 10)
    $aMainButton1[3] = (@DesktopWidth / 10) * 2
    $aMainButton1[4] = (@DesktopWidth / 10) * 2
    $aMainButton1[5] = $bRed
    $aMainButton1[6] = $bDarkRed
    Dim $aMainButton2[7]
    $aMainButton2[0] = 1
    $aMainButton2[1] = @DesktopWidth / 2 - (@DesktopWidth / 10) + 0.5 *@DesktopWidth
    $aMainButton2[2] = @DesktopHeight / 2 - (@DesktopWidth / 10)
    $aMainButton2[3] = (@DesktopWidth / 10) * 2
    $aMainButton2[4] = (@DesktopWidth / 10) * 2
    $aMainButton2[5] = $bBlue
    $aMainButton2[6] = $bDarkBlue
    Dim $aMainButton3[7]
    $aMainButton3[0] = 2
    $aMainButton3[1] = @DesktopWidth / 2 - (@DesktopWidth / 10) + @DesktopWidth
    $aMainButton3[2] = @DesktopHeight / 2 - (@DesktopWidth / 10)
    $aMainButton3[3] = (@DesktopWidth / 10) * 2
    $aMainButton3[4] = (@DesktopWidth / 10) * 2
    $aMainButton3[5] = $bGreen
    $aMainButton3[6] = $bDarkGreen
    Dim $aMainButton4[7]
    $aMainButton4[0] = 3
    $aMainButton4[1] = @DesktopWidth / 2 - (@DesktopWidth / 10) + (1.5 * @DesktopWidth)
    $aMainButton4[2] = @DesktopHeight / 2 - (@DesktopWidth / 10)
    $aMainButton4[3] = (@DesktopWidth / 10) * 2
    $aMainButton4[4] = (@DesktopWidth / 10) * 2
    $aMainButton4[5] = $bRed
    $aMainButton4[6] = $bDarkRed
    Dim $aMainButton5[7]
    $aMainButton5[0] = 4
    $aMainButton5[1] = @DesktopWidth / 2 - (@DesktopWidth / 10) + (2 * @DesktopWidth)
    $aMainButton5[2] = @DesktopHeight / 2 - (@DesktopWidth / 10)
    $aMainButton5[3] = (@DesktopWidth / 10) * 2
    $aMainButton5[4] = (@DesktopWidth / 10) * 2
    $aMainButton5[5] = $bBlue
    $aMainButton5[6] = $bDarkBlue
    Dim $aMainButton6[7]
    $aMainButton6[0] = 5
    $aMainButton6[1] = @DesktopWidth / 2 - (@DesktopWidth / 10) + (2.5 * @DesktopWidth)
    $aMainButton6[2] = @DesktopHeight / 2 - (@DesktopWidth / 10)
    $aMainButton6[3] = (@DesktopWidth / 10) * 2
    $aMainButton6[4] = (@DesktopWidth / 10) * 2
    $aMainButton6[5] = $bGreen
    $aMainButton6[6] = $bDarkGreen
    Dim $aMainButton7[5]
    $aMainButton7[0] = 0
    $aMainButton7[1] = @DesktopWidth * 0.96
    $aMainButton7[2] = @DesktopHeight * 0.01
    $aMainButton7[3] = (@DesktopWidth / 100) * 2
    $aMainButton7[4] = (@DesktopWidth / 100) * 2
    Dim $aAButton[7]
    $aAButton[0] = 6
    $aAButton[1] = $aMainButton1
    $aAButton[2] = $aMainButton2
    $aAButton[3] = $aMainButton3
    $aAButton[4] = $aMainButton4
    $aAButton[5] = $aMainButton5
    $aAButton[6] = $aMainButton6
    #endregion

    [/autoit] [autoit][/autoit] [autoit]

    _Draw_Graphics($hGraphic,$hDC_Window,$hDC_Bitmap,$SliderX,$SliderY, $bDimGrey)

    [/autoit] [autoit][/autoit] [autoit]

    $Timer = TimerInit()
    $FPS = 0

    [/autoit] [autoit][/autoit] [autoit]

    While True
    If TimerDiff($Timer) >= 1000 Then
    ToolTip("FPS:" & $FPS)
    $FPS = 0
    $Timer = TimerInit()
    Else
    $FPS += 1
    EndIf
    $Mouse = GUIGetCursorInfo($hGui_Main)
    If $Mouse[0] < $SliderX + $SliderWidth And $Mouse[0] > $SliderX Then
    If $Mouse[1] < (@DesktopHeight * 0.95) + 20 And $Mouse[1] > @DesktopHeight * 0.95 Then
    If $Mouse[2] == 1 Then
    $MouseDiffX = $Mouse[0] - $SliderX
    Do
    $Mouse = GUIGetCursorInfo($hGui_Main)
    If $Mouse[0] - $MouseDiffX >= @DesktopWidth / 7 And $Mouse[0] - $MouseDiffX + $SliderWidth <= @DesktopWidth - (@DesktopWidth / 7) Then
    $SliderX = $Mouse[0] - $MouseDiffX
    $SliderPerc = Round((($SliderX - (@DesktopWidth / 7)) / (@DesktopWidth - (3 * (@DesktopWidth / 7)))) * 100)
    EndIf
    $aMainButton1 = _Button_Event($aMainButton1,$SliderX)
    $aMainButton2 = _Button_Event($aMainButton2,$SliderX)
    $aMainButton3 = _Button_Event($aMainButton3,$SliderX)
    $aMainButton4 = _Button_Event($aMainButton4,$SliderX)
    $aMainButton5 = _Button_Event($aMainButton5,$SliderX)
    $aMainButton6 = _Button_Event($aMainButton6,$SliderX)

    [/autoit] [autoit][/autoit] [autoit]

    $aAButton[1] = $aMainButton1
    $aAButton[2] = $aMainButton2
    $aAButton[3] = $aMainButton3
    $aAButton[4] = $aMainButton4
    $aAButton[5] = $aMainButton5
    $aAButton[6] = $aMainButton6

    [/autoit] [autoit][/autoit] [autoit]

    $SliderX_New = $SliderX

    [/autoit] [autoit][/autoit] [autoit]

    _Clear_Buffer($hGraphic)
    _Draw_BG($hGraphic)
    For $i = 1 To $aAButton[0] Step 1
    $aTemp = $aAButton[$i]
    _Draw_RoundCorner_Button($hGraphic,"Button-" & $i,$aTemp[1],$aTemp[2],$aTemp[3],$aTemp[4],20,$aTemp[5])
    Next
    _Draw_RoundCorner_Button($hGraphic,"X",$aMainButton7[1],$aMainButton7[2],$aMainButton7[3],$aMainButton7[4],20,$bRed)
    _Draw_Graphics($hGraphic,$hDC_Window,$hDC_Bitmap,$SliderX,$SliderY, $bDarkGrey)
    Until $Mouse[2] == 0
    ;Else
    ;$MouseDiffX = 0
    EndIf
    EndIf
    EndIf
    _Clear_Buffer($hGraphic)
    _Draw_BG($hGraphic)
    If $Mouse[0] < $aMainButton7[1] + $aMainButton7[3] And $Mouse[0] > $aMainButton7[1] And $Mouse[1] < $aMainButton7[2] + $aMainButton7[4] And $Mouse[1] > $aMainButton7[2] Then
    _Draw_RoundCorner_Button($hGraphic,"X",$aMainButton7[1],$aMainButton7[2],$aMainButton7[3],$aMainButton7[4],20,$bDarkRed)
    If $Mouse[2] == 1 Then _Exit()
    Else
    _Draw_RoundCorner_Button($hGraphic,"X",$aMainButton7[1],$aMainButton7[2],$aMainButton7[3],$aMainButton7[4],20,$bRed)
    EndIf
    For $i = 1 To $aAButton[0] Step 1
    $aTemp = $aAButton[$i]
    If $Mouse[0] < $aTemp[1] + $aTemp[3] And $Mouse[0] > $aTemp[1] And $Mouse[1] < $aTemp[2] + $aTemp[4] And $Mouse[1] > $aTemp[2] Then
    _Draw_RoundCorner_Button($hGraphic,"Button-" & $i,$aTemp[1],$aTemp[2],$aTemp[3],$aTemp[4],20,$aTemp[6])
    If $Mouse[2] == 1 Then
    Switch $i
    Case 1

    [/autoit] [autoit][/autoit] [autoit]

    Case 2

    [/autoit] [autoit][/autoit] [autoit]

    Case 3

    [/autoit] [autoit][/autoit] [autoit]

    Case 4

    [/autoit] [autoit][/autoit] [autoit]

    Case 5

    [/autoit] [autoit][/autoit] [autoit]

    Case 6

    [/autoit] [autoit][/autoit] [autoit]

    EndSwitch
    EndIf
    Else
    _Draw_RoundCorner_Button($hGraphic,"Button-" & $i,$aTemp[1],$aTemp[2],$aTemp[3],$aTemp[4],20,$aTemp[5])
    EndIf
    Next
    _Draw_Graphics($hGraphic,$hDC_Window,$hDC_Bitmap,$SliderX,$SliderY, $bDimGrey)
    WEnd

    [/autoit] [autoit][/autoit] [autoit]

    Func _Draw_Graphics($hGr,$hDCw,$hDCb,$sx,$sy,$b1)
    Local $Font
    _GDIPlus_GraphicsDrawRect($hGr,(@DesktopWidth / 7) - 5,(@DesktopHeight * 0.95) - 5,@DesktopWidth - (2 *(@DesktopWidth / 7)) + 10,30)
    _GDIPlus_GraphicsFillRect($hGr,$sx,$sy,$SliderWidth,20,$b1)
    $Font = _GetTextLabelWidth("MyGui", "Arial", 60)
    _GDIPlus_GraphicsDrawString($hGr,"MyGui",@DesktopWidth / 2 - $Font / 2,20,"Arial",60)
    _WinAPI_BitBlt($hDCw, 0, 0, @DesktopWidth, @DesktopHeight, $hDCb, 0, 0, $SRCCOPY)
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    Func _Draw_BG($hBu)
    _GDIPlus_GraphicsDrawImageRect($hBu,$BG,0,0,@DesktopWidth,@DesktopHeight)
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    Func _Button_Event($aB,$s)
    Local $diff
    If $SliderX_New < $SliderX Then
    $diff = $s - $SliderX_New
    $aB[1] -= 4 * $diff
    Else
    If $SliderX_New > $SliderX Then
    $diff = $SliderX_New - $s
    $aB[1] += 4 * $diff
    EndIf
    EndIf
    Return $aB
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    Func _Exit()
    _WinAPI_SelectObject($hDC_Bitmap, $hOldObj)
    _WinAPI_ReleaseDC($hWnd, $hDC_Window)
    _WinAPI_DeleteDC($hDC_Bitmap)
    _WinAPI_DeleteObject($hBitmap)

    [/autoit] [autoit][/autoit] [autoit]

    _GDIPlus_GraphicsDispose($hGraphics)
    _GDIPlus_BrushDispose($bRed)
    _GDIPlus_BrushDispose($bDarkRed)
    _GDIPlus_BrushDispose($bBlue)
    _GDIPlus_BrushDispose($bDarkBlue)
    _GDIPlus_BrushDispose($bGreen)
    _GDIPlus_BrushDispose($bDarkGreen)
    _GDIPlus_BrushDispose($bDimGrey)
    _GDIPlus_BrushDispose($bDarkGrey)
    _GDIPlus_Shutdown()
    Exit
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    Func _GetTextLabelWidth($s_WinText, $s_TextFont, $i_FontSize, $i_FontWeight = -1)
    Local Const $DEFAULT_CHARSET = 0 ; ANSI character set
    Local Const $OUT_CHARACTER_PRECIS = 2
    Local Const $CLIP_DEFAULT_PRECIS = 0
    Local Const $PROOF_QUALITY = 2
    Local Const $FIXED_PITCH = 1
    Local Const $RGN_XOR = 3
    Local Const $LOGPIXELSY = 90

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    $h_WinTitle = "Get Label Width"
    If $i_FontWeight = "" Or $i_FontWeight = -1 Then $i_FontWeight = 600 ; default Font weight
    Local $h_GUI = GUICreate($h_WinTitle, 10, 10, -100, -100, $WS_POPUPWINDOW, $WS_EX_TOOLWINDOW)
    Local $hDC = DllCall("user32.dll", "int", "GetDC", "hwnd", $h_GUI)

    [/autoit] [autoit][/autoit] [autoit]

    Local $intDeviceCap = DllCall("gdi32.dll", "long", "GetDeviceCaps", "int", $hDC[0], "long", $LOGPIXELSY)
    $intDeviceCap = $intDeviceCap[0]

    [/autoit] [autoit][/autoit] [autoit]

    Local $intFontHeight = DllCall("kernel32.dll", "long", "MulDiv", "long", $i_FontSize, "long", $intDeviceCap, "long", 72)
    $intFontHeight = -$intFontHeight[0]

    [/autoit] [autoit][/autoit] [autoit]

    Local $hMyFont = DllCall("gdi32.dll", "hwnd", "CreateFont", "int", $intFontHeight, _
    "int", 0, "int", 0, "int", 0, "int", $i_FontWeight, "int", 0, _
    "int", 0, "int", 0, "int", $DEFAULT_CHARSET, _
    "int", $OUT_CHARACTER_PRECIS, "int", $CLIP_DEFAULT_PRECIS, _
    "int", $PROOF_QUALITY, "int", $FIXED_PITCH, "str", $s_TextFont)
    DllCall("gdi32.dll", "hwnd", "SelectObject", "int", $hDC[0], "hwnd", $hMyFont[0])

    [/autoit] [autoit][/autoit] [autoit]

    Local $res = DllStructCreate("int;int")

    [/autoit] [autoit][/autoit] [autoit]

    Local $ret = DllCall("gdi32.dll", "int", "GetTextExtentPoint32", "int", $hDC[0], "str", $s_WinText, "long", StringLen($s_WinText), "ptr", DllStructGetPtr($res))

    [/autoit] [autoit][/autoit] [autoit]

    Local $intLabelWidth = DllStructGetData($res,1)

    [/autoit] [autoit][/autoit] [autoit]

    GUIDelete($h_GUI)
    Return $intLabelWidth
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    Func _Clear_Buffer($hBu)
    _GDIPlus_GraphicsClear($hBu,0xFFFFFFFF)
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    Func _Draw_RoundCorner_Button($hGr,$TXT,$sX,$sY,$W,$H,$r,$C)
    Local $Font
    If $CPU_MIN Then
    ;Rundungen
    _GDIPlus_GraphicsFillEllipse($hGr,$sX,$sY,2 * $r,2 * $r,$C)
    _GDIPlus_GraphicsFillEllipse($hGr,$sX + $W - 2 * $r,$sY,2 * $r,2 * $r,$C)
    _GDIPlus_GraphicsFillEllipse($hGr,$sX,$sY + $H - 2 * $r,2 * $r,2 * $r,$C)
    _GDIPlus_GraphicsFillEllipse($hGr,$sX + $W - 2 * $r,$sY + $H - 2 * $r,2 * $r,2 * $r,$C)
    ;Fläche
    _GDIPlus_GraphicsFillRect($hGr,$sX,$sY + $r,$W,$H - (2 * $r),$C)
    _GDIPlus_GraphicsFillRect($hGr,$sX + $r,$sY,$W - (2 * $r),$r + 1,$C)
    _GDIPlus_GraphicsFillRect($hGr,$sX + $r,$sY + $H - $r - 1,$W - (2* $r),$r + 1,$C)
    ;Text
    $Font = _GetTextLabelWidth($TXT, "Arial", 16)
    _GDIPlus_GraphicsDrawString($hGr,$TXT,$sX + ($W / 2) - $Font / 2,$sY + ($H / 2) - 10,"Arial",16)
    Else
    _GDIPlus_GraphicsFillRect($hGr,$sX,$sY,$W,$H,$C)
    $Font = _GetTextLabelWidth($TXT, "Arial", 16)
    _GDIPlus_GraphicsDrawString($hGr,$TXT,$sX + ($W / 2) - $Font / 2,$sY + ($H / 2) - 10,"Arial",16)
    EndIf
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    Func _Redraw()
    _WinAPI_BitBlt($hDC_Window, 0, 0, @DesktopWidth, @DesktopHeight, $hDC_Bitmap, 0, 0, $SRCCOPY)
    EndFunc

    [/autoit]
  • Hi,
    frag dich mal, aus welchem Grund jemand x-mal in der Sekunde haufenweise Buttons und anderes Gedöns in ein Fenster "zeichnen" sollte, obwohl sich in diesem Fenster garnichts tut?!
    Wieso zeichnest du nicht die Buttons in ein Fenster und stellst es EINMAL dar und fragst dann nur noch die Buttonevents ab?

    Fürs waagrechte Scrollen einen kostenlosen Speedtip^^:
    Erstelle eine Bitmap mit der Größe (Gesamtbreite x HöheScreenx0.9). Die Gesamtbreite ist die von dir vorgegebene Größe des scrollbaren Bereichs, sagen wir mal 10000 Pixel.
    In diese Bitmap zeichnest du deine zu scrollenden Buttons.
    Jetzt musst du nur noch mit einem BitBlt() den vom Slider angegebenen Bereich, also gewissermaßen einen Ausschnitt deiner Grafik (die Buttons) in das Fenster blitten.
    Die HöheScreen wird nur mit 0.9 (oder 0.5 oder 0.4) multipliziert, da du nur den Streifen brauchst, den du scrollen willst, im Extremfall also nur einen Streifen von der Höhe der Buttons.

    Du kannst natürlich auch einfach jeden einzelnen Button aus einer Bitmap heraus in dein Fenster blitten, aber alles ist schneller, als den Button jedes mal neu zu zeichnen!

    ciao
    Andy


    "Schlechtes Benehmen halten die Leute doch nur deswegen für eine Art Vorrecht, weil keiner ihnen aufs Maul haut." Klaus Kinski
    "Hint: Write comments after each line. So you can (better) see what your program does and what it not does. And we can see what you're thinking what your program does and we can point to the missunderstandings." A-Jay

    Wie man Fragen richtig stellt... Tutorial: Wie man Script-Fehler findet und beseitigt...X-Y-Problem

    Einmal editiert, zuletzt von Andy (29. April 2013 um 20:53)

  • Danke für den Tipp ;)
    Aber das ich die ganzen Buttons neu zeichne ohne das was passiert ist ja eigentlich Nebensache auch beim Scrollen sind die FPS sehr niedrig und das war ja Hauptsächlich das Problem wenn da niemand scrollt kann die FPS ja auf 1 sinken weil man es da nicht bemerkt :D
    Aber trotzdem danke für die Hilfe ich werde versuchen es so umzubauen wie du es gesagt hattest ;)