neazoi Posted March 15, 2016 Share Posted March 15, 2016 Hi, I have made a javascript program that can create online electronics schematics http://5.54.115.143/jlab/cad/schematic/index.html It works like a puzzle. You pick an image from the table above and then you place it into the table below (blank area). That way you create schematics, like a puzzle. I would like to move this functionality from javascript to autoit. Is there any example of puzzle (pick and place into grid functionality), so that it can help me begin with the development? Thank you Link to comment Share on other sites More sharing options...
InunoTaishou Posted March 15, 2016 Share Posted March 15, 2016 I don't think I've seen anything like that, but what you're wanting to do could be done in GDI+ pretty easily. I had most of these already done from past scripts so it was mostly just copied/pasted. Except for the table, I did spend a little extra time making the images look like a table just because I thought it looked pretty It's up to you to create your work area and snap the images together. expandcollapse popup#include <GUIConstants.au3> #include <GDIPlus.au3> #include <WinApi.au3> #include <WindowsConstants.au3> #include <Array.au3> _GDIPlus_Startup() Global Const $iGuiWidth = 808 Global Const $iGuiHeight = 600 Global Const $iTablePadding = 12 Global Const $hSepPen = _GDIPlus_PenCreate(0xFF000000, 4) Global Const $hWorkBrush = _GDIPlus_BrushCreateSolid(0xFFFFFFFF) Global Const $hBackBrush = _GDIPlus_BrushCreateSolid(0x4F97FFFE) Global $aGDIPBuffer[1][5] ; Buffer holds the information of the work area. [n][0] will be the image [n][1] is left position, [n][2] is top position, [n][3] is right position, [n][4] is bottom position of the image Global $iImageWidth = 0 Global $iImageHeight = 0 Global $aGDIImageList = LoadGdiImageList($iImageWidth, $iImageHeight, $iGuiWidth, $iGuiHeight) Global $frmMainGui = GUICreate("Puzzle", $iGuiWidth, $iGuiHeight) Global $hGraphic = _GDIPlus_GraphicsCreateFromHWND($frmMainGui) Global $hBitmap = _GDIPlus_BitmapCreateFromGraphics($iGuiWidth, $iGuiHeight, $hGraphic) Global $hBuffer = _GDIPlus_ImageGetGraphicsContext($hBitmap) GUIRegisterMsg($WM_PAINT, WM_PAINT) GUIRegisterMsg($WM_LBUTTONDOWN, WM_LBUTTONDOWN) GUISetState(@SW_SHOW, $frmMainGui) While (True) Switch (GUIGetMsg()) Case $GUI_EVENT_CLOSE ; Always clena up your resources when you're done with GDI+ DisposeGdiImageList($aGDIImageList) _GDIPlus_PenDispose($hSepPen) _GDIPlus_BrushDispose($hWorkBrush) _GDIPlus_BrushDispose($hBackBrush) _GDIPlus_Shutdown() GUIDelete($frmMainGui) Exit 0 EndSwitch WEnd Func LoadGdiImageList(ByRef $iMaxWidth, ByRef $iMaxHeight, Const ByRef $iGuiWidth, $iGuiHeight) Local $aImageList[51] Local $iCurrentIndex = 0 Local $iRows = 0 Local $iColumns = 0 For $i = 0 To UBound($aImageList) - 1 $aImageList[$i] = _GDIPlus_ImageLoadFromFile(@ScriptDir & "\Images\" & $i & ".gif") $iImageWidth = Max(_GDIPlus_ImageGetWidth($aImageList[$i]), $iMaxWidth) $iImageHeight = Max(_GDIPlus_ImageGetHeight($aImageList[$i]), $iMaxHeight) Next GetTableDimensions($iRows, $iColumns, $iGuiWidth, $iGuiHeight, UBound($aImageList), $iImageWidth, $iImageHeight) Local $aImageListReturn[$iRows][$iColumns] For $iRow = 0 To UBound($aImageListReturn, $UBOUND_ROWS) - 1 For $iColumn = 0 To UBound($aImageListReturn, $UBOUND_COLUMNS) - 1 $aImageListReturn[$iRow][$iColumn] = $aImageList[$iCurrentIndex] $iCurrentIndex += 1 If ($iCurrentIndex >= UBound($aImageList)) Then For $i = $iColumn To $iColumns $aImageListReturn[$iRow][$iColumn] = $aImageList[0] Next ExitLoop 2 EndIf Next Next Return $aImageListReturn EndFunc ;==>LoadGdiImageList Func DisposeGdiImageList(ByRef $aImageList) If (IsArray($aImageList)) Then For $iRow = 0 To UBound($aImageList, $UBOUND_ROWS) - 1 For $iColumn = 0 to UBound($aImageList, $UBOUND_COLUMNS) - 1 _GDIPlus_ImageDispose($aImageList[$iRow][$iColumn]) Next Next Else Return SetError(-1, 0, 0) EndIf Return 1 EndFunc ;==>DisposeGdiImageList Func Max(Const ByRef $lhs, Const ByRef $rhs) Return ($lhs > $rhs ? $lhs : $rhs) EndFunc ;==>Max Func GetTableDimensions(ByRef $iRows, ByRef $iColumns, $iMaxWidth, $iMaxHeight, $iCount, Const ByRef $iImageWidth, Const ByRef $iImageHeight) If ($iImageWidth = 0 Or $iImageHeight = 0 Or $iMaxWidth <= 20 Or $iMaxHeight <= 20) Then Return SetError(-1, 0, 0) ; Get the max columns. $iTablePadding for the left, right, and top of the table and $iTablePadding between each iamge $iColumns = Int(($iMaxWidth - ($iTablePadding * 2)) / ($iImageWidth + $iTablePadding)) $iRows = Ceiling($iCount / $iColumns) Return 1 EndFunc ;==>GetTableDimensions Func DrawGdipArea(Const $bDrawAtEnd = True) _GDIPlus_GraphicsClear($hBuffer, 0xFFF0F0F0) For $iRow = 0 To UBound($aGDIImageList, $UBOUND_ROWS) - 1 For $iColumn = 0 To UBound($aGDIImageList, $UBOUND_COLUMNS) - 1 Local $iLeft = $iTablePadding + ($iTablePadding * $iColumn) + ($iColumn * $iImageWidth) Local $iTop = $iTablePadding + ($iTablePadding * $iRow) + ($iRow * $iImageHeight) Local $iRight = $iLeft + $iImageWidth Local $iBottom = $iTop + $iImageHeight ; Draw border around image, 4px offset _GDIPlus_GraphicsDrawLine($hBuffer, $iLeft - 4, $iTop - 4, $iLeft - 4, $iBottom + 4) ; Left _GDIPlus_GraphicsDrawLine($hBuffer, $iRight + 4, $iTop - 4, $iRight + 4, $iBottom + 4) ; Right _GDIPlus_GraphicsDrawLine($hBuffer, $iLeft - 4, $iTop - 4, $iRight + 4, $iTop - 4) ; Top _GDIPlus_GraphicsDrawLine($hBuffer, $iLeft - 4, $iBottom + 4, $iRight + 4, $iBottom + 4) ; Bottom _GDIPlus_GraphicsDrawImageRect($hBuffer, $aGDIImageList[$iRow][$iColumn], $iLeft, $iTop, $iImageWidth, $iImageHeight) Next Next ; Draw border around the whole table, 8px offset ; Just to make it look pretty :) _GDIPlus_GraphicsDrawLine($hBuffer, $iTablePadding - 8, $iTablePadding - 8, $iTablePadding - 8, $iBottom + 8) ; Left _GDIPlus_GraphicsDrawLine($hBuffer, $iRight + 8, $iTablePadding - 8, $iRight + 8, $iBottom + 8) ; Right _GDIPlus_GraphicsDrawLine($hBuffer, $iTablePadding - 8, $iTablePadding - 8, $iRight + 8, $iTablePadding - 8) ; Top _GDIPlus_GraphicsDrawLine($hBuffer, $iTablePadding - 8, $iBottom + 8, $iRight + 8, $iBottom + 8) ; Bottom _GDIPlus_GraphicsFillRect($hBuffer, 0, $iBottom + 25, $iGuiWidth, $iGuiHeight - $iBottom, $hWorkBrush) ; There's an image at the top row If ($aGDIPBuffer[0][0]) Then For $iBuffer = 0 To UBound($aGDIPBuffer, $UBOUND_ROWS) - 1 _GDIPlus_GraphicsDrawImageRect($hBuffer, $aGDIPBuffer[$iBuffer][0], $aGDIPBuffer[$iBuffer][1], $aGDIPBuffer[$iBuffer][2], $iImageWidth, $iImageHeight) Next EndIf _GDIPlus_GraphicsDrawLine($hBuffer, 0, $iBottom + 25, $iGuiWidth, $iBottom + 25, $hSepPen) If ($bDrawAtEnd) Then _GDIPlus_GraphicsDrawImage($hGraphic, $hBitmap, 0, 0) Return True EndFunc ;==>DrawGdipArea Func WM_PAINT($hWndFrom, $iMsg, $wParam, $lParam) DrawGdipArea() Return $GUI_RUNDEFMSG EndFunc ;==>WM_PAINT Func WM_LBUTTONDOWN($hWndFrom, $iMsg, $wParam, $lParam) Local $iLButtonX = _WinAPI_LoWord($lParam) Local $iLButtonY = _WinAPI_HiWord($lParam) Local $iImageRow = -1 Local $iImageColumn = -1 Local $aCursorInfo = 0 Local $iGdipBufferIndex = UBound($aGDIPBuffer, $UBOUND_ROWS) Switch ($hWndFrom) Case $frmMainGui For $iRow = 0 To UBound($aGDIImageList, $UBOUND_ROWS) - 1 For $iColumn = 0 To UBound($aGDIImageList, $UBOUND_COLUMNS) - 1 Local $iLeft = $iTablePadding + ($iTablePadding * $iColumn) + ($iColumn * $iImageWidth) Local $iTop = $iTablePadding + ($iTablePadding * $iRow) + ($iRow * $iImageHeight) Local $iRight = $iLeft + $iImageWidth Local $iBottom = $iTop + $iImageHeight If (_WinAPI_PtInRectEx($iLButtonX, $iLButtonY, $iLeft, $iTop, $iRight, $iBottom)) Then $iImageRow = $iRow $iImageColumn = $iColumn ExitLoop EndIf Next Next If ($iImageRow > -1 And $iImageColumn > -1) Then $aCursorInfo = GUIGetCursorInfo($hWndFrom) If (@error) Then Return $GUI_RUNDEFMSG While ($aCursorInfo[2]) Local $iLeft = $aCursorInfo[0] - Int($iImageWidth / 2) Local $iTop = $aCursorInfo[1] - Int($iImageHeight / 2) DrawGdipArea(False) _GDIPlus_GraphicsFillRect($hBuffer, $iLeft, $iTop, $iImageWidth, $iImageHeight, $hBackBrush) _GDIPlus_GraphicsDrawImageRect($hBuffer, $aGDIImageList[$iImageRow][$iImageColumn], $iLeft, $iTop, $iImageWidth, $iImageHeight) _GDIPlus_GraphicsDrawImage($hGraphic, $hBitmap, 0, 0) $aCursorInfo = GUIGetCursorInfo($hWndFrom) If (@error) Then Return $GUI_RUNDEFMSG WEnd $aGDIPBuffer[$iGdipBufferIndex - 1][0] = $aGDIImageList[$iImageRow][$iImageColumn] $aGDIPBuffer[$iGdipBufferIndex - 1][1] = $iLeft $aGDIPBuffer[$iGdipBufferIndex - 1][2] = $iTop $aGDIPBuffer[$iGdipBufferIndex - 1][3] = $iLeft + $iImageWidth $aGDIPBuffer[$iGdipBufferIndex - 1][4] = $iTop + $iImageHeight ReDim $aGDIPBuffer[$iGdipBufferIndex + 1][5] DrawGdipArea() EndIf EndSwitch Return $GUI_RUNDEFMSG EndFunc ;==>WM_LBUTTONDOWN Some notes: Spoiler Quote You'll notice $aGDIPBuffer at the top of the script. I used something like this when I was trying to make a small image editor in GDI+. This holds the information of what to draw, where, and how tall in your work area. The [n][0] position holds the image to draw, [n][1] is the left position, [n][2] is the top, [n][3] is the right, and [n][4] is the bottom position of the image to draw. Having your buffer like this will also make it easier to delete images from the work area. In the WM_LBUTTONDOWN function I used _WinAPI_PtInRectEx to check what available images is being selected, based on the same algorithm I used to draw the images in the DrawGdipArea function. When you want to remove or move your images in the work area you can use the same thing since you stored all the points you need. You could do this with labels/pic control to figure out what image you're over but I used this way. Do whatever you prefer. If you wanted to use some kind of button to change your available circuits, you'll have to either create a separate GUI to hold the buttons or create them in an area outside the $hBitmap area (Currently it's the whole GUI).  Anyways, it's a good base to get you started, since you probably don't know much, anything, about GDI+. neazoi 1 Link to comment Share on other sites More sharing options...
neazoi Posted March 16, 2016 Author Share Posted March 16, 2016 7 hours ago, InunoTaishou said: I don't think I've seen anything like that, but what you're wanting to do could be done in GDI+ pretty easily. I had most of these already done from past scripts so it was mostly just copied/pasted. Except for the table, I did spend a little extra time making the images look like a table just because I thought it looked pretty It's up to you to create your work area and snap the images together. expandcollapse popup#include <GUIConstants.au3> #include <GDIPlus.au3> #include <WinApi.au3> #include <WindowsConstants.au3> #include <Array.au3> _GDIPlus_Startup() Global Const $iGuiWidth = 808 Global Const $iGuiHeight = 600 Global Const $iTablePadding = 12 Global Const $hSepPen = _GDIPlus_PenCreate(0xFF000000, 4) Global Const $hWorkBrush = _GDIPlus_BrushCreateSolid(0xFFFFFFFF) Global Const $hBackBrush = _GDIPlus_BrushCreateSolid(0x4F97FFFE) Global $aGDIPBuffer[1][5] ; Buffer holds the information of the work area. [n][0] will be the image [n][1] is left position, [n][2] is top position, [n][3] is right position, [n][4] is bottom position of the image Global $iImageWidth = 0 Global $iImageHeight = 0 Global $aGDIImageList = LoadGdiImageList($iImageWidth, $iImageHeight, $iGuiWidth, $iGuiHeight) Global $frmMainGui = GUICreate("Puzzle", $iGuiWidth, $iGuiHeight) Global $hGraphic = _GDIPlus_GraphicsCreateFromHWND($frmMainGui) Global $hBitmap = _GDIPlus_BitmapCreateFromGraphics($iGuiWidth, $iGuiHeight, $hGraphic) Global $hBuffer = _GDIPlus_ImageGetGraphicsContext($hBitmap) GUIRegisterMsg($WM_PAINT, WM_PAINT) GUIRegisterMsg($WM_LBUTTONDOWN, WM_LBUTTONDOWN) GUISetState(@SW_SHOW, $frmMainGui) While (True) Switch (GUIGetMsg()) Case $GUI_EVENT_CLOSE ; Always clena up your resources when you're done with GDI+ DisposeGdiImageList($aGDIImageList) _GDIPlus_PenDispose($hSepPen) _GDIPlus_BrushDispose($hWorkBrush) _GDIPlus_BrushDispose($hBackBrush) _GDIPlus_Shutdown() GUIDelete($frmMainGui) Exit 0 EndSwitch WEnd Func LoadGdiImageList(ByRef $iMaxWidth, ByRef $iMaxHeight, Const ByRef $iGuiWidth, $iGuiHeight) Local $aImageList[51] Local $iCurrentIndex = 0 Local $iRows = 0 Local $iColumns = 0 For $i = 0 To UBound($aImageList) - 1 $aImageList[$i] = _GDIPlus_ImageLoadFromFile(@ScriptDir & "\Images\" & $i & ".gif") $iImageWidth = Max(_GDIPlus_ImageGetWidth($aImageList[$i]), $iMaxWidth) $iImageHeight = Max(_GDIPlus_ImageGetHeight($aImageList[$i]), $iMaxHeight) Next GetTableDimensions($iRows, $iColumns, $iGuiWidth, $iGuiHeight, UBound($aImageList), $iImageWidth, $iImageHeight) Local $aImageListReturn[$iRows][$iColumns] For $iRow = 0 To UBound($aImageListReturn, $UBOUND_ROWS) - 1 For $iColumn = 0 To UBound($aImageListReturn, $UBOUND_COLUMNS) - 1 $aImageListReturn[$iRow][$iColumn] = $aImageList[$iCurrentIndex] $iCurrentIndex += 1 If ($iCurrentIndex >= UBound($aImageList)) Then For $i = $iColumn To $iColumns $aImageListReturn[$iRow][$iColumn] = $aImageList[0] Next ExitLoop 2 EndIf Next Next Return $aImageListReturn EndFunc ;==>LoadGdiImageList Func DisposeGdiImageList(ByRef $aImageList) If (IsArray($aImageList)) Then For $iRow = 0 To UBound($aImageList, $UBOUND_ROWS) - 1 For $iColumn = 0 to UBound($aImageList, $UBOUND_COLUMNS) - 1 _GDIPlus_ImageDispose($aImageList[$iRow][$iColumn]) Next Next Else Return SetError(-1, 0, 0) EndIf Return 1 EndFunc ;==>DisposeGdiImageList Func Max(Const ByRef $lhs, Const ByRef $rhs) Return ($lhs > $rhs ? $lhs : $rhs) EndFunc ;==>Max Func GetTableDimensions(ByRef $iRows, ByRef $iColumns, $iMaxWidth, $iMaxHeight, $iCount, Const ByRef $iImageWidth, Const ByRef $iImageHeight) If ($iImageWidth = 0 Or $iImageHeight = 0 Or $iMaxWidth <= 20 Or $iMaxHeight <= 20) Then Return SetError(-1, 0, 0) ; Get the max columns. $iTablePadding for the left, right, and top of the table and $iTablePadding between each iamge $iColumns = Int(($iMaxWidth - ($iTablePadding * 2)) / ($iImageWidth + $iTablePadding)) $iRows = Ceiling($iCount / $iColumns) Return 1 EndFunc ;==>GetTableDimensions Func DrawGdipArea(Const $bDrawAtEnd = True) _GDIPlus_GraphicsClear($hBuffer, 0xFFF0F0F0) For $iRow = 0 To UBound($aGDIImageList, $UBOUND_ROWS) - 1 For $iColumn = 0 To UBound($aGDIImageList, $UBOUND_COLUMNS) - 1 Local $iLeft = $iTablePadding + ($iTablePadding * $iColumn) + ($iColumn * $iImageWidth) Local $iTop = $iTablePadding + ($iTablePadding * $iRow) + ($iRow * $iImageHeight) Local $iRight = $iLeft + $iImageWidth Local $iBottom = $iTop + $iImageHeight ; Draw border around image, 4px offset _GDIPlus_GraphicsDrawLine($hBuffer, $iLeft - 4, $iTop - 4, $iLeft - 4, $iBottom + 4) ; Left _GDIPlus_GraphicsDrawLine($hBuffer, $iRight + 4, $iTop - 4, $iRight + 4, $iBottom + 4) ; Right _GDIPlus_GraphicsDrawLine($hBuffer, $iLeft - 4, $iTop - 4, $iRight + 4, $iTop - 4) ; Top _GDIPlus_GraphicsDrawLine($hBuffer, $iLeft - 4, $iBottom + 4, $iRight + 4, $iBottom + 4) ; Bottom _GDIPlus_GraphicsDrawImageRect($hBuffer, $aGDIImageList[$iRow][$iColumn], $iLeft, $iTop, $iImageWidth, $iImageHeight) Next Next ; Draw border around the whole table, 8px offset ; Just to make it look pretty :) _GDIPlus_GraphicsDrawLine($hBuffer, $iTablePadding - 8, $iTablePadding - 8, $iTablePadding - 8, $iBottom + 8) ; Left _GDIPlus_GraphicsDrawLine($hBuffer, $iRight + 8, $iTablePadding - 8, $iRight + 8, $iBottom + 8) ; Right _GDIPlus_GraphicsDrawLine($hBuffer, $iTablePadding - 8, $iTablePadding - 8, $iRight + 8, $iTablePadding - 8) ; Top _GDIPlus_GraphicsDrawLine($hBuffer, $iTablePadding - 8, $iBottom + 8, $iRight + 8, $iBottom + 8) ; Bottom _GDIPlus_GraphicsFillRect($hBuffer, 0, $iBottom + 25, $iGuiWidth, $iGuiHeight - $iBottom, $hWorkBrush) ; There's an image at the top row If ($aGDIPBuffer[0][0]) Then For $iBuffer = 0 To UBound($aGDIPBuffer, $UBOUND_ROWS) - 1 _GDIPlus_GraphicsDrawImageRect($hBuffer, $aGDIPBuffer[$iBuffer][0], $aGDIPBuffer[$iBuffer][1], $aGDIPBuffer[$iBuffer][2], $iImageWidth, $iImageHeight) Next EndIf _GDIPlus_GraphicsDrawLine($hBuffer, 0, $iBottom + 25, $iGuiWidth, $iBottom + 25, $hSepPen) If ($bDrawAtEnd) Then _GDIPlus_GraphicsDrawImage($hGraphic, $hBitmap, 0, 0) Return True EndFunc ;==>DrawGdipArea Func WM_PAINT($hWndFrom, $iMsg, $wParam, $lParam) DrawGdipArea() Return $GUI_RUNDEFMSG EndFunc ;==>WM_PAINT Func WM_LBUTTONDOWN($hWndFrom, $iMsg, $wParam, $lParam) Local $iLButtonX = _WinAPI_LoWord($lParam) Local $iLButtonY = _WinAPI_HiWord($lParam) Local $iImageRow = -1 Local $iImageColumn = -1 Local $aCursorInfo = 0 Local $iGdipBufferIndex = UBound($aGDIPBuffer, $UBOUND_ROWS) Switch ($hWndFrom) Case $frmMainGui For $iRow = 0 To UBound($aGDIImageList, $UBOUND_ROWS) - 1 For $iColumn = 0 To UBound($aGDIImageList, $UBOUND_COLUMNS) - 1 Local $iLeft = $iTablePadding + ($iTablePadding * $iColumn) + ($iColumn * $iImageWidth) Local $iTop = $iTablePadding + ($iTablePadding * $iRow) + ($iRow * $iImageHeight) Local $iRight = $iLeft + $iImageWidth Local $iBottom = $iTop + $iImageHeight If (_WinAPI_PtInRectEx($iLButtonX, $iLButtonY, $iLeft, $iTop, $iRight, $iBottom)) Then $iImageRow = $iRow $iImageColumn = $iColumn ExitLoop EndIf Next Next If ($iImageRow > -1 And $iImageColumn > -1) Then $aCursorInfo = GUIGetCursorInfo($hWndFrom) If (@error) Then Return $GUI_RUNDEFMSG While ($aCursorInfo[2]) Local $iLeft = $aCursorInfo[0] - Int($iImageWidth / 2) Local $iTop = $aCursorInfo[1] - Int($iImageHeight / 2) DrawGdipArea(False) _GDIPlus_GraphicsFillRect($hBuffer, $iLeft, $iTop, $iImageWidth, $iImageHeight, $hBackBrush) _GDIPlus_GraphicsDrawImageRect($hBuffer, $aGDIImageList[$iImageRow][$iImageColumn], $iLeft, $iTop, $iImageWidth, $iImageHeight) _GDIPlus_GraphicsDrawImage($hGraphic, $hBitmap, 0, 0) $aCursorInfo = GUIGetCursorInfo($hWndFrom) If (@error) Then Return $GUI_RUNDEFMSG WEnd $aGDIPBuffer[$iGdipBufferIndex - 1][0] = $aGDIImageList[$iImageRow][$iImageColumn] $aGDIPBuffer[$iGdipBufferIndex - 1][1] = $iLeft $aGDIPBuffer[$iGdipBufferIndex - 1][2] = $iTop $aGDIPBuffer[$iGdipBufferIndex - 1][3] = $iLeft + $iImageWidth $aGDIPBuffer[$iGdipBufferIndex - 1][4] = $iTop + $iImageHeight ReDim $aGDIPBuffer[$iGdipBufferIndex + 1][5] DrawGdipArea() EndIf EndSwitch Return $GUI_RUNDEFMSG EndFunc ;==>WM_LBUTTONDOWN Some notes:  Reveal hidden contents  Anyways, it's a good base to get you started, since you probably don't know much, anything, about GDI+. There must be an error somewhere, or something is happening with the includes. C:\Users\Desktop\schematic.au3 (23) : ==> Missing separator character after keyword.: GUIRegisterMsg($WM_PAINT, WM_PAINT) GUIRegisterMsg($WM_PAINT, WM_PAINT^ ERROR Link to comment Share on other sites More sharing options...
InunoTaishou Posted March 16, 2016 Share Posted March 16, 2016 Did you modify it? What version of AutoIt do you have? Link to comment Share on other sites More sharing options...
neazoi Posted March 16, 2016 Author Share Posted March 16, 2016 (edited) 16 minutes ago, InunoTaishou said: Did you modify it? What version of AutoIt do you have? I did not modify it. I just installed the newest version of autoit just to make sure. Now the error is: "C:\Users\Desktop\Schematix.au3" (125) : ==> Variable used without being declared.: _GDIPlus_GraphicsDrawLine($hBuffer, $iTablePadding - 8, $iTablePadding - 8, $iTablePadding - 8, $iBottom + 8) _GDIPlus_GraphicsDrawLine($hBuffer, $iTablePadding - 8, $iTablePadding - 8, $iTablePadding - 8, ^ ERROR Edited March 16, 2016 by neazoi Link to comment Share on other sites More sharing options...
InunoTaishou Posted March 16, 2016 Share Posted March 16, 2016 You need to load the images properly. I named them all 0-49 Use this Example.rar Example.rar neazoi 1 Link to comment Share on other sites More sharing options...
neazoi Posted March 16, 2016 Author Share Posted March 16, 2016 (edited) Ok I declared the $iLeft $iTop $iRight $iBottom at the beginning and it worked. Thanks so much for the script! thumbs up!! How would you do it if you wanted the pieces to be dropped into predefined positions, like in the javascript program I sent you? Â That way, one does not need to accurately place one image next to the other. PS. I wonder, why it did not work in the previous version... Edited March 16, 2016 by neazoi Link to comment Share on other sites More sharing options...
InunoTaishou Posted March 16, 2016 Share Posted March 16, 2016 The reason that error occurred is because they're declared inside the for loops and will only get declared when you actually have the images loaded (or image, it only needs 1). If the images for the grid are not loaded then it never goes into the double for loop and never declares the variables needed to draw the border around the images properly. neazoi 1 Link to comment Share on other sites More sharing options...
neazoi Posted March 16, 2016 Author Share Posted March 16, 2016 45 minutes ago, InunoTaishou said: The reason that error occurred is because they're declared inside the for loops and will only get declared when you actually have the images loaded (or image, it only needs 1). If the images for the grid are not loaded then it never goes into the double for loop and never declares the variables needed to draw the border around the images properly. Yes I have noticed that, thanks a lot. How would you do it if you wanted the pieces to be dropped into predefined positions, like in the javascript program I sent you? That way, one does not need to accurately place one image next to the other. and the pieces are pasted always in predefined positions onto a grid. Any ideas? Link to comment Share on other sites More sharing options...
InunoTaishou Posted March 16, 2016 Share Posted March 16, 2016 Well I see that the first three rows are always the same. You could load the images into a const array of the default images So modify the LoadGdiImageList function a bit expandcollapse popupGlobal $aGDIImageList = LoadGdiImageListFromFolder(@ScriptDir & "\Images\Default\", $iImageWidth, $iImageHeight, $iGuiWidth, $iGuiHeight) Func LoadGdiImageListFromFolder(Const ByRef $sFilePath, ByRef $iMaxWidth, ByRef $iMaxHeight, Const ByRef $iGuiWidth, $iGuiHeight) Local $aImageList[0] Local $iCurrentIndex = 0 Local $iRows = 0 Local $iColumns = 0 Local $aImages = _FileListToArray($sFilePath, "*.gif", $FLTA_FILES) If (@error) Then Return SetError(-1, 0, $aImageList) _ArrayDelete($aImages, 0) For $i = 0 To UBound($aImages) - 1 For $p = $i To UBound($aImages) - 1 If (Number(StringLeft($aImages[$i], StringInStr($aImages[$i], ".") - 1)) > Number(StringLeft($aImages[$p], StringInStr($aImages[$p], ".") - 1))) Then _ArraySwap($aImages, $i, $p) EndIf Next Next For $i = 0 To UBound($aImages) - 1 Local $iIndex = UBound($aImageList) ReDim $aImageList[$iIndex + 1] $aImageList[$iIndex] = _GDIPlus_ImageLoadFromFile($sFilePath & $aImages[$i]) $iImageWidth = Max(_GDIPlus_ImageGetWidth($aImageList[$iIndex]), $iMaxWidth) $iImageHeight = Max(_GDIPlus_ImageGetHeight($aImageList[$iIndex]), $iMaxHeight) Next GetTableDimensions($iRows, $iColumns, $iGuiWidth, $iGuiHeight, UBound($aImageList), $iImageWidth, $iImageHeight) Local $aImageListReturn[$iRows][$iColumns] For $iRow = 0 To UBound($aImageListReturn, $UBOUND_ROWS) - 1 For $iColumn = 0 To UBound($aImageListReturn, $UBOUND_COLUMNS) - 1 $aImageListReturn[$iRow][$iColumn] = $aImageList[$iCurrentIndex] $iCurrentIndex += 1 If ($iCurrentIndex >= UBound($aImageList)) Then For $i = $iColumn To $iColumns $aImageListReturn[$iRow][$iColumn] = $aImageList[0] Next ExitLoop 2 EndIf Next Next Return $aImageListReturn EndFunc ;==>LoadGdiImageListFromFolder Set all the default images in a folder called default. These are the first 3 rows that did not change. Now when you want to change out the last row you call the same function but with the directory you want and store the result in a temporary array (it's still a 2d array but it should have 1 row and 15 columns). Free the images in the $aGDIImageList that you're replacing (you can make the function however you want to do that, or modify the DisposeGdiImageList to something like DisposeGdiImageList(ByRef $aImageList, $iRowStart, $iRowEnd, $iColumnStart, $iColumnEnd). Finally, copy over the loaded images from the temporary array to the $aGDIImageList array. You'll have to think about if there is an image in the work area that's no longer in your table. Once you dispose the image in GDI+ it won't be able to draw it anymore. Maybe instead of working with one GDIImageList array you could work with 1 default one that's always drawn and another 27 for the other components, or a 2d GDIImageList array. Having the default images in the 0 index. Then, depending on which component to see, you draw all the images at the n index. That would solve the issue of drawing an image that was replaced by some other image, since we're not storing the index for the GDIImageList array where the image is but the address to the image in the Buffer. If that makes sense. I'd personally just load all of the possible images and just use a button to scroll left/right or up/down through the images, or buttons that will scroll to where the specific components are. It's up to you, it's your project, I can get you started but I won't do it all for you. neazoi 1 Link to comment Share on other sites More sharing options...
neazoi Posted March 17, 2016 Author Share Posted March 17, 2016 (edited) 19 hours ago, InunoTaishou said: Well I see that the first three rows are always the same. You could load the images into a const array of the default images So modify the LoadGdiImageList function a bit expandcollapse popupGlobal $aGDIImageList = LoadGdiImageListFromFolder(@ScriptDir & "\Images\Default\", $iImageWidth, $iImageHeight, $iGuiWidth, $iGuiHeight) Func LoadGdiImageListFromFolder(Const ByRef $sFilePath, ByRef $iMaxWidth, ByRef $iMaxHeight, Const ByRef $iGuiWidth, $iGuiHeight) Local $aImageList[0] Local $iCurrentIndex = 0 Local $iRows = 0 Local $iColumns = 0 Local $aImages = _FileListToArray($sFilePath, "*.gif", $FLTA_FILES) If (@error) Then Return SetError(-1, 0, $aImageList) _ArrayDelete($aImages, 0) For $i = 0 To UBound($aImages) - 1 For $p = $i To UBound($aImages) - 1 If (Number(StringLeft($aImages[$i], StringInStr($aImages[$i], ".") - 1)) > Number(StringLeft($aImages[$p], StringInStr($aImages[$p], ".") - 1))) Then _ArraySwap($aImages, $i, $p) EndIf Next Next For $i = 0 To UBound($aImages) - 1 Local $iIndex = UBound($aImageList) ReDim $aImageList[$iIndex + 1] $aImageList[$iIndex] = _GDIPlus_ImageLoadFromFile($sFilePath & $aImages[$i]) $iImageWidth = Max(_GDIPlus_ImageGetWidth($aImageList[$iIndex]), $iMaxWidth) $iImageHeight = Max(_GDIPlus_ImageGetHeight($aImageList[$iIndex]), $iMaxHeight) Next GetTableDimensions($iRows, $iColumns, $iGuiWidth, $iGuiHeight, UBound($aImageList), $iImageWidth, $iImageHeight) Local $aImageListReturn[$iRows][$iColumns] For $iRow = 0 To UBound($aImageListReturn, $UBOUND_ROWS) - 1 For $iColumn = 0 To UBound($aImageListReturn, $UBOUND_COLUMNS) - 1 $aImageListReturn[$iRow][$iColumn] = $aImageList[$iCurrentIndex] $iCurrentIndex += 1 If ($iCurrentIndex >= UBound($aImageList)) Then For $i = $iColumn To $iColumns $aImageListReturn[$iRow][$iColumn] = $aImageList[0] Next ExitLoop 2 EndIf Next Next Return $aImageListReturn EndFunc ;==>LoadGdiImageListFromFolder Set all the default images in a folder called default. These are the first 3 rows that did not change. Now when you want to change out the last row you call the same function but with the directory you want and store the result in a temporary array (it's still a 2d array but it should have 1 row and 15 columns). Free the images in the $aGDIImageList that you're replacing (you can make the function however you want to do that, or modify the DisposeGdiImageList to something like DisposeGdiImageList(ByRef $aImageList, $iRowStart, $iRowEnd, $iColumnStart, $iColumnEnd). Finally, copy over the loaded images from the temporary array to the $aGDIImageList array. You'll have to think about if there is an image in the work area that's no longer in your table. Once you dispose the image in GDI+ it won't be able to draw it anymore. Maybe instead of working with one GDIImageList array you could work with 1 default one that's always drawn and another 27 for the other components, or a 2d GDIImageList array. Having the default images in the 0 index. Then, depending on which component to see, you draw all the images at the n index. That would solve the issue of drawing an image that was replaced by some other image, since we're not storing the index for the GDIImageList array where the image is but the address to the image in the Buffer. If that makes sense. I'd personally just load all of the possible images and just use a button to scroll left/right or up/down through the images, or buttons that will scroll to where the specific components are. It's up to you, it's your project, I can get you started but I won't do it all for you. Â Thank you very much for the code snippet, It has been very helpful! To draw electronics schematics one needs to put labels for the components, near them. I do not want to convert the text into image and place the image to a position, but instead I was wondering if this drag and drop for images you have done, can be done for text as well? What I need is to type the text into a form box and then to be able to place this text (drag and drop? or click?) to a specific area of the schematic (puzzle). The text positions should be held in the $aGDIPBuffer, similar to the images, because I want to export/import it's data later on. Would that it be easy to be done somehow? Edited March 17, 2016 by neazoi Link to comment Share on other sites More sharing options...
InunoTaishou Posted March 17, 2016 Share Posted March 17, 2016 If you're wanting to draw a string Then you can use _GDIPlus_GraphicsDrawString or _GDIPlus_GraphicsDrawStringEx _GDIPlus_GraphicsDrawStringEx will draw a string to fit in a defined rectangle and only draw what will fit. I.e., if you just want the string to fit in a label that's 100px wide and 20px tall. _GDIPlus_GraphicsDrawString will draw the string until all of the letters are drawn. Here's a small snippit to get you going. I just used DrawString but you can use whichever you prefer. Also, I created my graphic a bit different in this example than the other. I created it using an HDC based off of a label I created. This lets me place all of my "stuff" only where the label is, instead of the whole GUI. I need to use this instead of CreateFromHwnd because of the input box. Since FromHwnd would have created a graphic object the size of the whole gui, whenever you draw any images it's going to cover up the input box. expandcollapse popup#include <GDIPlus.au3> #include <GUIConstantsEx.au3> #include <WindowsConstants.au3> #include <EditConstants.au3> #include <WinAPI.au3> _GDIPlus_Startup() ; Width and Height of my work area Global const $iWidth = 380 Global Const $iHeight = 260 Global $hGUI = GUICreate("GDI+", 400, 300) Global $hInput = GUICtrlCreateInput("Custom String", 10, 10, 100, 20) Global $lblDc = GUICtrlCreateLabel("", 10, 30, $iWidth, $iHeight) Global $hDc = _WinAPI_GetWindowDC(GUICtrlGetHandle($lblDc)) Global $hGraphic = _GDIPlus_GraphicsCreateFromHDC($hDc) Global $hBitmap = _GDIPlus_BitmapCreateFromGraphics($iWidth, $iHeight, $hGraphic) Global $hBuffer = _GDIPlus_ImageGetGraphicsContext($hBitmap) Global $hBitmapLabel = 0 GUIRegisterMsg($WM_COMMAND, WM_COMMAND) GUISetState(@SW_SHOW) DrawCustomLabel(GUICtrlRead($hInput)) While (True) Local $aCursorInfo Switch (GUIGetMsg()) Case $GUI_EVENT_CLOSE _GDIPlus_GraphicsDispose($hGraphic) _GDIPlus_Shutdown() GUIDelete($hGUI) Exit 0 Case $lblDc $aCursorInfo = GUIGetCursorInfo() If (Not @Error) Then If (_WinAPI_PtInRectEx($aCursorInfo[0], $aCursorInfo[1], 10, 30, 110, 130)) Then $hBitmapLabel = _GDIPlus_BitmapCloneArea($hBitmap, 0, 0, 101, 21) While ($aCursorInfo[2]) MoveLabel($aCursorInfo[0], $aCursorInfo[1], GUICtrlRead($hInput)) Sleep(100) $aCursorInfo = GUIGetCursorInfo() WEnd EndIf EndIf EndSwitch WEnd Func MoveLabel(Const ByRef $iNewX, Const ByRef $iNewY, Const ByRef $sText) DrawCustomLabel($sText) ; Draw it 10px to the left and 30px up because my work area is based off the position of the $lblDc label. Which is 10px right and 30px down. _GDIPlus_GraphicsDrawImage($hGraphic, $hBitmapLabel, $iNewX - 10, $iNewY - 30) EndFunc Func DrawCustomLabel(Const ByRef $sText) _GDIPlus_GraphicsClear($hBuffer, 0xFFF0F0F0) _GDIPlus_GraphicsDrawString($hBuffer, $sText, 0, 5) _GDIPlus_GraphicsDrawRect($hBuffer, 0, 0, 100, 20) _GDIPlus_GraphicsDrawImage($hGraphic, $hBitmap, 0, 0) EndFunc Func WM_COMMAND($hWndFrom, $iMsg, $wParam, $lParam) Local $iCode = _WinAPI_HiWord($wParam) Local $iIdFrom = _WinAPI_LoWord($wParam) Switch ($hWndFrom) Case $hGUI Switch ($iIdFrom) Case $hInput Switch ($iCode) Case $EN_CHANGE DrawCustomLabel(GUICtrlRead($hInput)) EndSwitch EndSwitch EndSwitch Return $GUI_RUNDEFMSG EndFunc ;==>WM_COMMAND I'm rushed for time but if you have questions post and I or someone else will answer. neazoi 1 Link to comment Share on other sites More sharing options...
InunoTaishou Posted March 17, 2016 Share Posted March 17, 2016 Just to add on to that. I used _GDIPlus_BitmapCloneArea($hBitmap, 0, 0, 101, 21) Because we've already drawn the string (and I drew it with a border, 101, 21). So I just copied the drawn area. You can just redraw the string each time if you want. neazoi 1 Link to comment Share on other sites More sharing options...
neazoi Posted March 18, 2016 Author Share Posted March 18, 2016 (edited) 22 hours ago, InunoTaishou said: Just to add on to that. I used _GDIPlus_BitmapCloneArea($hBitmap, 0, 0, 101, 21) Because we've already drawn the string (and I drew it with a border, 101, 21). So I just copied the drawn area. You can just redraw the string each time if you want. I saw your example and this is exactly what needed. However due to my lack of good knowledge obviously, I am confused in embedding it into my (yours) application. The code I have is this (minor graphics mods to yours). I just need the functuonality you provided but each label must be a new copy to the area, so that the previous label is not overwritten or deleted, each time I put a new label. The position and the text label should be kept into the $aGDIPBuffer, like it is done for the images (if I understand this correctly), so that I can export it later on. Instead of the image name, the label text could be kept. It would be great if you could help me embed it to this example. Thanks so much for your time! expandcollapse popup;You'll notice $aGDIPBuffer at the top of the script. I used something like this when I was trying to make a small image editor in GDI+. ;This holds the information of what to draw, where, and how tall in your work area. The [n][0] position holds the image to draw, [n][1] is the left position, ;[n][2] is the top, [n][3] is the right, and [n][4] is the bottom position of the image to draw. Having your buffer like this will also make it easier ;to delete images from the work area. ;In the WM_LBUTTONDOWN function I used _WinAPI_PtInRectEx to check what available images is being selected, based on the same algorithm I used to draw ;the images in the DrawGdipArea function. When you want to remove or move your images in the work area you can use the same thing since you stored all ;the points you need. You could do this with labels/pic control to figure out what image you're over but I used this way. Do whatever you prefer. ;If you wanted to use some kind of button to change your available circuits, you'll have to either create a separate GUI to hold the buttons or ;create them in an area outside the $hBitmap area (Currently it's the whole GUI). #include <GUIConstants.au3> #include <GUIConstantsEx.au3> #include <GDIPlus.au3> #include <WinApi.au3> #include <WindowsConstants.au3> #include <EditConstants.au3> #include <Array.au3> _GDIPlus_Startup() Global Const $iGuiWidth = 1501 ;Window width Global Const $iGuiHeight = 1010 ;Window height Global Const $iTablePadding = 8 ;padding of components cells Global Const $hSepPen = _GDIPlus_PenCreate(0xFF000000, 2) ;bgcolor and size of the separator line Global Const $hWorkBrush = _GDIPlus_BrushCreateSolid(0xFFFFFFFF) ;bgcolor of the schematic area Global Const $hBackBrush = _GDIPlus_BrushCreateSolid(0x4FFFFFFF) ;bgcolor of the dragged image Global $aGDIPBuffer[1][5] ;Buffer holds the information of the work area. ;[n][0] will be the image, ;[n][1] is left position, ;[n][2] is top position, ;[n][3] is right position, ;[n][4] is bottom position of the image Global $iImageWidth = 0 Global $iImageHeight = 0 Global $aGDIImageList = LoadGdiImageList($iImageWidth, $iImageHeight, $iGuiWidth, $iGuiHeight) Global $frmMainGui = GUICreate("Schematix v0.1 by sv3ora", $iGuiWidth, $iGuiHeight) Global $hGraphic = _GDIPlus_GraphicsCreateFromHWND($frmMainGui) Global $hBitmap = _GDIPlus_BitmapCreateFromGraphics($iGuiWidth, $iGuiHeight, $hGraphic) Global $hBuffer = _GDIPlus_ImageGetGraphicsContext($hBitmap) GUIRegisterMsg($WM_PAINT, WM_PAINT) GUIRegisterMsg($WM_LBUTTONDOWN, WM_LBUTTONDOWN) GUISetState(@SW_SHOW, $frmMainGui) GUISetCursor("5") ;set the window cursor to a predefined image (0-16) While (True) Switch (GUIGetMsg()) Case $GUI_EVENT_CLOSE ; Always clean up your resources when you're done with GDI+ DisposeGdiImageList($aGDIImageList) _GDIPlus_PenDispose($hSepPen) _GDIPlus_BrushDispose($hWorkBrush) _GDIPlus_BrushDispose($hBackBrush) _GDIPlus_Shutdown() GUIDelete($frmMainGui) Exit 0 EndSwitch WEnd Func LoadGdiImageList(ByRef $iMaxWidth, ByRef $iMaxHeight, Const ByRef $iGuiWidth, $iGuiHeight) Local $aImageList[330] ;how many images to be displayed Local $iCurrentIndex = 0 Local $iRows = 0 Local $iColumns = 0 For $i = 0 To UBound($aImageList) - 1 $aImageList[$i] = _GDIPlus_ImageLoadFromFile(@ScriptDir & "\Imagestodelete\" & $i & ".gif") $iImageWidth = Max(_GDIPlus_ImageGetWidth($aImageList[$i]), $iMaxWidth) $iImageHeight = Max(_GDIPlus_ImageGetHeight($aImageList[$i]), $iMaxHeight) Next GetTableDimensions($iRows, $iColumns, $iGuiWidth, $iGuiHeight, UBound($aImageList), $iImageWidth, $iImageHeight) Local $aImageListReturn[$iRows][$iColumns] For $iRow = 0 To UBound($aImageListReturn, $UBOUND_ROWS) - 1 For $iColumn = 0 To UBound($aImageListReturn, $UBOUND_COLUMNS) - 1 $aImageListReturn[$iRow][$iColumn] = $aImageList[$iCurrentIndex] $iCurrentIndex += 1 If ($iCurrentIndex >= UBound($aImageList)) Then For $i = $iColumn To $iColumns $aImageListReturn[$iRow][$iColumn] = $aImageList[0] Next ExitLoop 2 EndIf Next Next Return $aImageListReturn EndFunc ;==>LoadGdiImageList Func DisposeGdiImageList(ByRef $aImageList) If (IsArray($aImageList)) Then For $iRow = 0 To UBound($aImageList, $UBOUND_ROWS) - 1 For $iColumn = 0 to UBound($aImageList, $UBOUND_COLUMNS) - 1 _GDIPlus_ImageDispose($aImageList[$iRow][$iColumn]) Next Next Else Return SetError(-1, 0, 0) EndIf Return 1 EndFunc ;==>DisposeGdiImageList Func Max(Const ByRef $lhs, Const ByRef $rhs) Return ($lhs > $rhs ? $lhs : $rhs) EndFunc ;==>Max Func GetTableDimensions(ByRef $iRows, ByRef $iColumns, $iMaxWidth, $iMaxHeight, $iCount, Const ByRef $iImageWidth, Const ByRef $iImageHeight) If ($iImageWidth = 0 Or $iImageHeight = 0 Or $iMaxWidth <= 20 Or $iMaxHeight <= 20) Then Return SetError(-1, 0, 0) ; Get the max columns. $iTablePadding for the left, right, and top of the table and $iTablePadding between each iamge $iColumns = Int(($iMaxWidth - ($iTablePadding * 2)) / ($iImageWidth + $iTablePadding)) $iRows = Ceiling($iCount / $iColumns) Return 1 EndFunc ;==>GetTableDimensions Func DrawGdipArea(Const $bDrawAtEnd = True) _GDIPlus_GraphicsClear($hBuffer, 0xFFE1E1E1) ;bgcolor of the components area For $iRow = 0 To UBound($aGDIImageList, $UBOUND_ROWS) - 1 For $iColumn = 0 To UBound($aGDIImageList, $UBOUND_COLUMNS) - 1 Local $iLeft = $iTablePadding + ($iTablePadding * $iColumn) + ($iColumn * $iImageWidth) Local $iTop = $iTablePadding + ($iTablePadding * $iRow) + ($iRow * $iImageHeight) Local $iRight = $iLeft + $iImageWidth Local $iBottom = $iTop + $iImageHeight ; Draw border around image, 4px offset ;_GDIPlus_GraphicsDrawLine($hBuffer, $iLeft - 4, $iTop - 4, $iLeft - 4, $iBottom + 4) ; Left ;_GDIPlus_GraphicsDrawLine($hBuffer, $iRight + 4, $iTop - 4, $iRight + 4, $iBottom + 4) ; Right ;_GDIPlus_GraphicsDrawLine($hBuffer, $iLeft - 4, $iTop - 4, $iRight + 4, $iTop - 4) ; Top ;_GDIPlus_GraphicsDrawLine($hBuffer, $iLeft - 4, $iBottom + 4, $iRight + 4, $iBottom + 4) ; Bottom _GDIPlus_GraphicsDrawImageRect($hBuffer, $aGDIImageList[$iRow][$iColumn], $iLeft, $iTop, $iImageWidth, $iImageHeight) Next Next ; Draw border around the whole table, 8px offset ; Just to make it look pretty :) ;_GDIPlus_GraphicsDrawLine($hBuffer, $iTablePadding - 8, $iTablePadding - 8, $iTablePadding - 8, $iBottom + 8) ; Left ;_GDIPlus_GraphicsDrawLine($hBuffer, $iRight + 8, $iTablePadding - 8, $iRight + 8, $iBottom + 8) ; Right ;_GDIPlus_GraphicsDrawLine($hBuffer, $iTablePadding - 8, $iTablePadding - 8, $iRight + 8, $iTablePadding - 8) ; Top ;_GDIPlus_GraphicsDrawLine($hBuffer, $iTablePadding - 8, $iBottom + 8, $iRight + 8, $iBottom + 8) ; Bottom _GDIPlus_GraphicsFillRect($hBuffer, 0, $iBottom + 25, $iGuiWidth, $iGuiHeight - $iBottom, $hWorkBrush) ; There's an image at the top row If ($aGDIPBuffer[0][0]) Then For $iBuffer = 0 To UBound($aGDIPBuffer, $UBOUND_ROWS) - 1 _GDIPlus_GraphicsDrawImageRect($hBuffer, $aGDIPBuffer[$iBuffer][0], $aGDIPBuffer[$iBuffer][1], $aGDIPBuffer[$iBuffer][2], $iImageWidth, $iImageHeight) Next EndIf _GDIPlus_GraphicsDrawLine($hBuffer, 0, $iBottom + 25, $iGuiWidth, $iBottom + 25, $hSepPen) If ($bDrawAtEnd) Then _GDIPlus_GraphicsDrawImage($hGraphic, $hBitmap, 0, 0) Return True EndFunc ;==>DrawGdipArea Func WM_PAINT($hWndFrom, $iMsg, $wParam, $lParam) DrawGdipArea() Return $GUI_RUNDEFMSG EndFunc ;==>WM_PAINT Func WM_LBUTTONDOWN($hWndFrom, $iMsg, $wParam, $lParam) Local $iLButtonX = _WinAPI_LoWord($lParam) Local $iLButtonY = _WinAPI_HiWord($lParam) Local $iImageRow = -1 Local $iImageColumn = -1 Local $aCursorInfo = 0 Local $iGdipBufferIndex = UBound($aGDIPBuffer, $UBOUND_ROWS) Switch ($hWndFrom) Case $frmMainGui For $iRow = 0 To UBound($aGDIImageList, $UBOUND_ROWS) - 1 For $iColumn = 0 To UBound($aGDIImageList, $UBOUND_COLUMNS) - 1 Local $iLeft = $iTablePadding + ($iTablePadding * $iColumn) + ($iColumn * $iImageWidth) Local $iTop = $iTablePadding + ($iTablePadding * $iRow) + ($iRow * $iImageHeight) Local $iRight = $iLeft + $iImageWidth Local $iBottom = $iTop + $iImageHeight If (_WinAPI_PtInRectEx($iLButtonX, $iLButtonY, $iLeft, $iTop, $iRight, $iBottom)) Then $iImageRow = $iRow $iImageColumn = $iColumn ExitLoop EndIf Next Next If ($iImageRow > -1 And $iImageColumn > -1) Then $aCursorInfo = GUIGetCursorInfo($hWndFrom) If (@error) Then Return $GUI_RUNDEFMSG While ($aCursorInfo[2]) Local $iLeft = $aCursorInfo[0] - Int($iImageWidth / 2) Local $iTop = $aCursorInfo[1] - Int($iImageHeight / 2) DrawGdipArea(False) _GDIPlus_GraphicsFillRect($hBuffer, $iLeft, $iTop, $iImageWidth, $iImageHeight, $hBackBrush) _GDIPlus_GraphicsDrawImageRect($hBuffer, $aGDIImageList[$iImageRow][$iImageColumn], $iLeft, $iTop, $iImageWidth, $iImageHeight) _GDIPlus_GraphicsDrawImage($hGraphic, $hBitmap, 0, 0) $aCursorInfo = GUIGetCursorInfo($hWndFrom) If (@error) Then Return $GUI_RUNDEFMSG WEnd $aGDIPBuffer[$iGdipBufferIndex - 1][0] = $aGDIImageList[$iImageRow][$iImageColumn] $aGDIPBuffer[$iGdipBufferIndex - 1][1] = $iLeft $aGDIPBuffer[$iGdipBufferIndex - 1][2] = $iTop $aGDIPBuffer[$iGdipBufferIndex - 1][3] = $iLeft + $iImageWidth $aGDIPBuffer[$iGdipBufferIndex - 1][4] = $iTop + $iImageHeight ReDim $aGDIPBuffer[$iGdipBufferIndex + 1][5] DrawGdipArea() EndIf EndSwitch Return $GUI_RUNDEFMSG EndFunc ;==>WM_LBUTTONDOWN Â Edited March 18, 2016 by neazoi Link to comment Share on other sites More sharing options...
InunoTaishou Posted March 18, 2016 Share Posted March 18, 2016 Alright, I modified my example to show you how to draw your display label and store the label in the buffer. I didn't like having the background color of 0xF0F0F0 (the default background color for all windows forms) so I decided to draw the string and then clone where the label ends up (after you let go of the mouse button). This gives you a background of wherever the label is placed. I believe I commented everything properly and explained it well. Adding #Region tags where I changed code and where I added new code. When you get the point where you want to move already placed images that are stored in your buffer you'll have to add an Else statement for the WM_LBUTTONDOWN function. If ($iImageRow > -1 And $iImageColumn > -1) Then ; Code for this section ElseIf (_WinAPI_PtInRectEx($iLButtonX, $iLButtonY, $tRectLabel.x, $tRectLabel.y, $tRectLabel.x + $iGuiWidthInput, $tRectLabel.y + $iGuiHeightInput)) Then ; Code for this section Else ; New else EndIf In the Else you'll then go through the GDIBuffer checking the [1], [2], [1] + [3], [2] + [4] (x, y, right, bottom). Then it's up to you to figure out how to move it on your work area Example.rar Link to comment Share on other sites More sharing options...
JAPP Posted March 19, 2016 Share Posted March 19, 2016 This is some cool stuff you two are doing here - I'm doing some things with stereo speaker crossover designs right now and I like this. I've tried some of the free schematics software on the net but I've found most of it overkill to the point where it is useless to me. I really love the straight-forward simplicity of this - I'll keep watching! Link to comment Share on other sites More sharing options...
qwert Posted March 19, 2016 Share Posted March 19, 2016 1 hour ago, JAPP said: I really love the straight-forward simplicity of this I concur ... and am following this, also. But (if it's not too much trouble) would someone mind posting a screen capture that will make the points easier to understand for me and others? Thanks. Link to comment Share on other sites More sharing options...
InunoTaishou Posted March 19, 2016 Share Posted March 19, 2016 GDI+ can get pretty complex but everything here is pretty simple so far. Some of the more complex stuff might just be some of the GDI+ function calls. First off, $aGDIPBuffer is just a workplace buffer. In simplistic terms it has the image to draw ([row][0]), where to draw it ([row][1] and [row][2] and the dimensions ([row][3] and [row][4]. aka. width, height) Next is Global $aGDIImageList = LoadGdiImageListFromFolder. The function (LoadGdiImageListFromFolder, in my example) just looks for all the .gif files in the specified folder. On the first for loop, in the function, (For $i = 0 and For $p = 0) all I'm doing is sorting the images logically. Since the images are just 0-49 (in my folder) and the _FileListToArray function doesn't get files alphabetically/numerically, I sorted them numerically. The second For loop loads all of the images into the $aImageList array (just a 1d array right now since I'll be arranging them a row, column array next) and saves the width and height of the widest and tallest image (all of his images from the website were 37x37px, but there could be an instance where one is 35x37. That 2px difference might not sound like much but when all the images are lined up in a grid, you might be able to see the difference). And finally, the last for loop. This is the real array. This is going to sort all of the images and store them in 2d array ([row][column]) so that it's displayed in the table on the gui. Where the images are saved in this array determines where they show up on the table. I.e., if image 37 is in row 1 column 6 in this array, it's in row 1 column 6 on the table. Everything else up to the GUIRegisterMsg stuff is just creating the work area of the GUI, creating the GUI, creating an input box (for the custom label), and creating the necessary objects for drawing a string (the label). Which you can read about from the help file. I register the WM_PAINT message because when a window is minimized then the GDI+ graphic object is erased. In fact, even on a regular GUI with regular controls, the controls are erased. But when you restore your GUI then windows tells that GUI you need to redraw your stuff. Default controls windows will handle, but GDI+ needs to be redrawn by the user. The WM_LBUTTONDOWN is for clicking on one of the images (more on this later) and WM_COMMAND is just to detect when the user is typing in the input box (so it updates the available label directly next to the input box. When you type in the box, it's redrawing the available label with your text) The DrawGdipArea function is where we draw everything for our graphic. There are much simpler examples in the help file and on the forums for drawing GDI+ so I'd suggest starting there first. My first for loop is the table at the very top of our GUI. I draw 4 lines around where the image is going to be (I'm drawing a border around where the image will be so the image looks like it's in a box, so it looks like a table). Then I draw the image, and I'm drawing it using DrawImageRect so that all of the images are the same width and height. The $bMoveOnce is because I didn't know how tall the table would be and I (personally) wanted the input box for the label to be directly below the table. You could draw the table lower and just put the input box at the top and not have to worry about it here in the loop. I then draw the string from the input box (using DrawStringEx so that the string fits into the defined area. If we just use DrawString and the input box has 100 characters then all 100 characters are going to be drawn on one line all the way to the end until everything is drawn or there's no more room on the GUI). Next is the border around the table, just to make it look pretty (I was just trying to mimic what his website looked like). And finally the buffer, going through each row of the buffer drawing the specified image at the correct position on the GUI. The WM_LBUTTONDOWN function might look intimidating but, basically, all it's doing is checking to see if the mouse is clicking on one of the images in the table. If it is then it will DrawGdipArea and then draw the image that you're clicking on. If you're left clicking an image from the table then it's going to draw that image where you move your mouse, if you're clicking on the custom label then it's going to draw that label where your mouse is. Finally, when you release the left button it's going to save the image, or the label, in the buffer and save where to draw it. TLDR; Creating a 2d array with the table images, detect if you click on an image or the label, if you're clicking an image or a label then draw that image or label where the mouse is, and save the image or label in your buffer. Like I said, this is actually pretty simple. GDI+ can get pretty complex and do so much more. I actually really liked this post and it gave me an idea. I'm making a puzzle game using wallpapers. Link to comment Share on other sites More sharing options...
JAPP Posted March 19, 2016 Share Posted March 19, 2016 InunoTaishou, Thanks for the explanation. I've been working/playing with AutoIt for several years now, but I've never touched GDI+. This will help me a lot. Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now