Zedna Posted May 16, 2011 Share Posted May 16, 2011 I need to draw dashed/dotted line with width=2 pixelsMSDN: LineTo/CreatePenhttp://msdn.microsoft.com/en-us/library/dd145029%28v=vs.85%29.aspxhttp://msdn.microsoft.com/en-us/library/dd183509%28v=vs.85%29.aspxAccording to MSDN LineTo uses current penand at CreatePen there is mentioned when style is PS_DASH or PS_DOT:This style is valid only when the pen width is one or less in device units.So how can I achieve dashed/dotted line with width=2 using Windows API/GDI?Note: I would like to use GDI (not GDI+) but I will be glad for any help.Here is simple testing script:#include <WindowsConstants.au3> #include <WinAPI.au3> ShowCross(@DesktopWidth / 2, @DesktopHeight / 2, 200, 1, 0xFF, 3000) ; width 1 Sleep(100) ShowCross(@DesktopWidth / 2, @DesktopHeight / 2, 200, 2, 0xFF, 3000) ; width 2 Func ShowCross($start_x, $start_y, $length, $width, $color, $time) Local $hDC, $hPen, $obj_orig $hDC = _WinAPI_GetWindowDC(0) ; DC of entire screen (desktop) ;~ $hPen = _WinAPI_CreatePen($PS_SOLID, $width, $color) ; OK $hPen = _WinAPI_CreatePen($PS_DOT, $width, $color) ; not OK $obj_orig = _WinAPI_SelectObject($hDC, $hPen) _WinAPI_MoveTo($hDC, $start_x, $start_y + $length) _WinAPI_LineTo($hDC, $start_x, $start_y + 5) ; test: draw two 1 pixel lines next to them ;~ _WinAPI_MoveTo($hDC, $start_x + 1, $start_y + $length) ;~ _WinAPI_LineTo($hDC, $start_x + 1, $start_y + 5) Sleep($time) ; show cross over screen for defined seconds ; refresh desktop (clear cross) _WinAPI_RedrawWindow(_WinAPI_GetDesktopWindow(), 0, 0, $RDW_INVALIDATE + $RDW_ALLCHILDREN) ; clear resources _WinAPI_SelectObject($hDC, $obj_orig) _WinAPI_DeleteObject($hPen) _WinAPI_ReleaseDC(0, $hDC) EndFunc ;==>ShowCross Resources UDF ResourcesEx UDF AutoIt Forum Search Link to comment Share on other sites More sharing options...
PsaltyDS Posted May 17, 2011 Share Posted May 17, 2011 (edited) This mod worked to draw two one-pixel dashed lines next to each other: #include <WindowsConstants.au3> #include <WinAPI.au3> For $w = 1 To 5 ShowCross(@DesktopWidth / 2, @DesktopHeight / 2, 100, $w, 0xFF, 3000) ; width 1 Next Func ShowCross($start_x, $start_y, $length, $width, $color, $time) Local $hDC, $hPen, $obj_orig $hDC = _WinAPI_GetWindowDC(0) ; DC of entire screen (desktop) $hPen = _WinAPI_CreatePen($PS_DOT, 1, $color) ; not OK $obj_orig = _WinAPI_SelectObject($hDC, $hPen) For $n = 0 To $width - 1 _WinAPI_MoveTo($hDC, $start_x + $n, $start_y + $length) _WinAPI_LineTo($hDC, $start_x + $n, $start_y + 5) Next Sleep($time) ; show cross over screen for defined seconds _WinAPI_RedrawWindow(_WinAPI_GetDesktopWindow(), 0, 0, $RDW_INVALIDATE + $RDW_ALLCHILDREN) _WinAPI_SelectObject($hDC, $obj_orig) _WinAPI_DeleteObject($hPen) _WinAPI_ReleaseDC(0, $hDC) EndFunc ;==>ShowCross Didn't attempt the logic to handle horizontal as well as a vertical line, but that should be simple. Edited May 17, 2011 by PsaltyDS Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law Link to comment Share on other sites More sharing options...
sleepydvdr Posted May 17, 2011 Share Posted May 17, 2011 I've been playing with it for a few minutes. This isn't working perfectly, but maybe it will get you moving in the right direction: expandcollapse popup#include <WindowsConstants.au3> #include <WinAPI.au3> ShowCross(@DesktopWidth / 2, @DesktopHeight / 2, 200, 1, 0xFF, 3000) ; width 1 Sleep(100) ShowCross(@DesktopWidth / 2, @DesktopHeight / 2, 200, 2, 0xFF, 3000) ; width 2 Func ShowCross($start_x, $start_y, $length, $width, $color, $time) Local $hDC, $hPen, $obj_orig $hDC = _WinAPI_GetWindowDC(0) ; DC of entire screen (desktop) ;~ $hPen = _WinAPI_CreatePen($PS_SOLID, $width, $color) ; OK $hPen = _WinAPI_CreatePen($PS_DOT, $width, $color) ; not OK $x_coord = $start_x ;Added this to go back to the original value. Apparently, the $start_x gets modified somewhere. $obj_orig = _WinAPI_SelectObject($hDC, $hPen) _WinAPI_MoveTo($hDC, $start_x, $start_y + $length) _WinAPI_LineTo($hDC, $start_x, $start_y + 5) _WinAPI_MoveTo($hDC, $x_coord +1, $start_y + $length) _WinAPI_LineTo($hDC, $x_coord +1, $start_y + 5) ; test: draw two 1 pixel lines next to them ;~ _WinAPI_MoveTo($hDC, $start_x + 1, $start_y + $length) ;~ _WinAPI_LineTo($hDC, $start_x + 1, $start_y + 5) Sleep($time) ; show cross over screen for defined seconds ; refresh desktop (clear cross) _WinAPI_RedrawWindow(_WinAPI_GetDesktopWindow(), 0, 0, $RDW_INVALIDATE + $RDW_ALLCHILDREN) ; clear resources _WinAPI_SelectObject($hDC, $obj_orig) _WinAPI_DeleteObject($hPen) _WinAPI_ReleaseDC(0, $hDC) EndFunc ;==>ShowCross #include <ByteMe.au3> Link to comment Share on other sites More sharing options...
rover Posted May 17, 2011 Share Posted May 17, 2011 entering 'Draw dotted line win32' on MSDN search, turned this up: http://stackoverflow.com/questions/541166/winapi-how-to-draw-dotted-line Creating a true dotted pen http://www.codeproject.com/KB/GDI/DOTTED_PEN.aspx problem is, it's also limited to one pixel but $PS_GEOMETRIC, $PS_DASH allow a sizeable dashed line, but... Problem using ExtCreatePen http://social.msdn.microsoft.com/Forums/en-US/vcgeneral/thread/7e1f58be-d534-48e2-83e5-2d2300077a8a possibly LineDDA() ? http://msdn.microsoft.com/en-us/library/dd145025(VS.85).aspx 2 pixel wide dashed line expandcollapse popup#include <WindowsConstants.au3> #include <WinAPI.au3> Global Const $PS_COSMETIC = 0x0 Global Const $PS_ALTERNATE = 8 Global Const $PS_GEOMETRIC = 0x10000 ShowCross(@DesktopWidth / 2, @DesktopHeight / 2, 400, 2, 0xFF0000, 8000) Func ShowCross($start_x, $start_y, $length, $width, $color, $time) Local $hDC, $hPen, $obj_orig $hDC = _WinAPI_GetWindowDC(0) ; DC of entire screen (desktop) ;$hPen = _WinAPI_CreatePen($PS_DOT, 1, $color);actually a dashed line, not a dotted line ;$hPen = _WinAPI_ExtCreatePen(BitOR($PS_COSMETIC, $PS_ALTERNATE), 1, 0xFF0000);true dotted line, but single pixel... $hPen = _WinAPI_ExtCreatePen(BitOR($PS_GEOMETRIC, $PS_DASH), $width, $Color);allows large dashed line $obj_orig = _WinAPI_SelectObject($hDC, $hPen) _WinAPI_DrawLine($hDC, $start_x - $length, $start_y, $start_x - 5, $start_y) ; horizontal left _WinAPI_DrawLine($hDC, $start_x + $length, $start_y, $start_x + 5, $start_y) ; horizontal right _WinAPI_DrawLine($hDC, $start_x, $start_y - $length, $start_x, $start_y - 5) ; vertical up ; _WinAPI_DrawLine($hDC, $start_x, $start_y + $length, $start_x, $start_y + 5) ; vertical down _WinAPI_MoveTo($hDC, $start_x, $start_y + $length) _WinAPI_LineTo($hDC, $start_x, $start_y + 5) Sleep($time) ; show cross over screen for defined seconds ; refresh desktop (clear cross) _WinAPI_RedrawWindow(_WinAPI_GetDesktopWindow(), 0, 0, $RDW_INVALIDATE + $RDW_ALLCHILDREN) ; clear resources _WinAPI_SelectObject($hDC, $obj_orig) _WinAPI_DeleteObject($hPen) _WinAPI_ReleaseDC(0, $hDC) EndFunc ;==>ShowCross Func _WinAPI_ExtCreatePen($iPenStyle, $iWidth, $nColor, $dwStyleCount = 0, $pStyle = 0) ;coded by rover 2k11: tagLOGBRUSH and _WinAPI_SwitchColor() from Yashied's WinAPIEx Local Const $tagLOGBRUSH = 'uint Style;dword Color;ulong_ptr Hatch;' ;from WinAPIEx Local Const $BS_SOLID = 0 Local $tLOGBRUSH = DllStructCreate($tagLOGBRUSH) DllStructSetData($tLOGBRUSH, 1, $BS_SOLID) DllStructSetData($tLOGBRUSH, 2, _WinAPI_SwitchColor($nColor)) DllStructSetData($tLOGBRUSH, 3, 0) Local $pLOGBRUSH = DllStructGetPtr($tLOGBRUSH) Local $aResult = DllCall("gdi32.dll", "handle", "ExtCreatePen", "dword", $iPenStyle, _ "dword", $iWidth, "ptr", $pLOGBRUSH, "dword", $dwStyleCount, "ptr", $pStyle) If @error Then Return SetError(@error, @extended, 0) Return $aResult[0] EndFunc ;==>_WinAPI_ExtCreatePen ;from WinAPIEx Func _WinAPI_SwitchColor($iColor) Return BitOR(BitAND($iColor, 0x00FF00), BitShift(BitAND($iColor, 0x0000FF), -16), BitShift(BitAND($iColor, 0xFF0000), 16)) EndFunc ;==>_WinAPI_SwitchColor I see fascists... Link to comment Share on other sites More sharing options...
rover Posted May 17, 2011 Share Posted May 17, 2011 even better: user style pens expandcollapse popup;even better: user style pens #include <WindowsConstants.au3> #include <WinAPI.au3> Global Const $PS_COSMETIC = 0x0 Global Const $PS_ALTERNATE = 8 Global Const $PS_GEOMETRIC = 0x10000 Global Const $PS_USERSTYLE = 7 Global Const $PS_ENDCAP_ROUND = 0x0 ShowCross(@DesktopWidth / 2, @DesktopHeight / 2, 400, 2, 0xFF0000, 2000);dashed ShowCross(@DesktopWidth / 2, @DesktopHeight / 2, 400, 2, 0xFF0000, 3000, 2, 4);dotted ShowCross(@DesktopWidth / 2, @DesktopHeight / 2, 400, 8, 0xFF0000, 2000, 2, 15);dotted ShowCross(@DesktopWidth / 2, @DesktopHeight / 2, 400, 12, 0xFF0000, 2000, 2, 30);dotted Func ShowCross($start_x, $start_y, $length, $width, $color, $time, $iElement1 = 0, $iElement2 = 0) Local $hDC, $hPen, $obj_orig $hDC = _WinAPI_GetWindowDC(0) ; DC of entire screen (desktop) ;$hPen = _WinAPI_CreatePen($PS_DOT, 1, $color);actually a dashed line, not a dotted line ;$hPen = _WinAPI_ExtCreatePen(BitOR($PS_COSMETIC, $PS_ALTERNATE), 1, 0xFF0000);true dotted line, but single pixel... If $iElement1 > 0 And $iElement1 > 0 Then $hPen = _WinAPI_ExtCreatePen(BitOR($PS_GEOMETRIC, $PS_USERSTYLE), $width, $Color, $iElement1, $iElement2);allows large dotted line Else $hPen = _WinAPI_ExtCreatePen(BitOR($PS_GEOMETRIC, $PS_DASH), $width, $Color);allows large dashed line EndIf $obj_orig = _WinAPI_SelectObject($hDC, $hPen) _WinAPI_DrawLine($hDC, $start_x - $length, $start_y, $start_x - 5, $start_y) ; horizontal left _WinAPI_DrawLine($hDC, $start_x + $length, $start_y, $start_x + 5, $start_y) ; horizontal right _WinAPI_DrawLine($hDC, $start_x, $start_y - $length, $start_x, $start_y - 5) ; vertical up ; _WinAPI_DrawLine($hDC, $start_x, $start_y + $length, $start_x, $start_y + 5) ; vertical down _WinAPI_MoveTo($hDC, $start_x, $start_y + $length) _WinAPI_LineTo($hDC, $start_x, $start_y + 5) Sleep($time) ; show cross over screen for defined seconds ; refresh desktop (clear cross) _WinAPI_RedrawWindow(_WinAPI_GetDesktopWindow(), 0, 0, $RDW_INVALIDATE + $RDW_ALLCHILDREN) ; clear resources _WinAPI_SelectObject($hDC, $obj_orig) _WinAPI_DeleteObject($hPen) _WinAPI_ReleaseDC(0, $hDC) EndFunc ;==>ShowCross Func _WinAPI_ExtCreatePen($iPenStyle, $iWidth, $nColor, $iStyle1 = 0, $iStyle2 = 0) ;coded by rover 2k11: tagLOGBRUSH and _WinAPI_SwitchColor() from Yashied's WinAPIEx Local Const $tagLOGBRUSH = 'uint Style;dword Color;ulong_ptr Hatch;' ;from WinAPIEx Local Const $BS_SOLID = 0 Local $tLOGBRUSH = DllStructCreate($tagLOGBRUSH) DllStructSetData($tLOGBRUSH, 1, $BS_SOLID) DllStructSetData($tLOGBRUSH, 2, _WinAPI_SwitchColor($nColor)) DllStructSetData($tLOGBRUSH, 3, 0);can be 0 for solid brush Local $pLOGBRUSH = DllStructGetPtr($tLOGBRUSH) If $iStyle1 > 0 And $iStyle2 > 0 Then Local $tUserStyle = DllStructCreate("dword;dword") DllStructSetData($tUserStyle, 1, $iStyle1) DllStructSetData($tUserStyle, 2, $iStyle2) $pStyle = DllStructGetPtr($tUserStyle) $dwStyleCount = DllStructGetSize($tUserStyle)/4 Else $pStyle = 0 $dwStyleCount = 0 EndIf Local $aResult = DllCall("gdi32.dll", "handle", "ExtCreatePen", "dword", $iPenStyle, _ "dword", $iWidth, "ptr", $pLOGBRUSH, "dword", $dwStyleCount, "ptr", $pStyle) If @error Then Return SetError(@error, @extended, 0) Return $aResult[0] EndFunc ;==>_WinAPI_ExtCreatePen ;from WinAPIEx Func _WinAPI_SwitchColor($iColor) Return BitOR(BitAND($iColor, 0x00FF00), BitShift(BitAND($iColor, 0x0000FF), -16), BitShift(BitAND($iColor, 0xFF0000), 16)) EndFunc ;==>_WinAPI_SwitchColor I see fascists... Link to comment Share on other sites More sharing options...
Zedna Posted May 17, 2011 Author Share Posted May 17, 2011 (edited) Amazing rover!! Much stuff to play with :-) Many thanks EDIT: thanks others too but that way I tested already and wanted to know clean API functions like rover showed Edited May 17, 2011 by Zedna Resources UDF ResourcesEx UDF AutoIt Forum Search Link to comment Share on other sites More sharing options...
UEZ Posted May 17, 2011 Share Posted May 17, 2011 (edited) I know you don't want to use GDI+ but here my solution with GDI and GDI+: expandcollapse popup#Include <GDIPlus.au3> #include <WindowsConstants.au3> #include <WinAPI.au3> ShowCross(@DesktopWidth / 2, @DesktopHeight / 2, @DesktopWidth / 2, @DesktopHeight / 2 + 200, 2, 0xFFFF0000) ShowCross(@DesktopWidth / 2 + 200, @DesktopHeight / 2, @DesktopWidth / 2 + 200, @DesktopHeight / 2 + 200, 2, 0xFFFF0000) ShowCross(@DesktopWidth / 2, @DesktopHeight / 2, @DesktopWidth / 2 + 200, @DesktopHeight / 2, 2, 0xFFFF0000) ShowCross(@DesktopWidth / 2, @DesktopHeight / 2 + 200, @DesktopWidth / 2 + 200, @DesktopHeight / 2 + 200, 2, 0xFFFF0000) ShowCross(@DesktopWidth / 3, @DesktopHeight / 3, @DesktopWidth / 3, @DesktopHeight / 3 + 200, 1, 0xFFFF0000) ShowCross(@DesktopWidth / 3 + 200, @DesktopHeight / 3, @DesktopWidth / 3 + 200, @DesktopHeight / 3 + 200, 1, 0xFFFF0000) ShowCross(@DesktopWidth / 3, @DesktopHeight / 3, @DesktopWidth / 3 + 200, @DesktopHeight / 3, 1, 0xFFFF0000) ShowCross(@DesktopWidth / 3, @DesktopHeight / 3 + 200, @DesktopWidth / 3 + 200, @DesktopHeight / 3 + 200, 1, 0xFFFF0000) Sleep(3000) ;~ refresh desktop (clear cross) _WinAPI_RedrawWindow(_WinAPI_GetDesktopWindow(), 0, 0, $RDW_INVALIDATE + $RDW_ALLCHILDREN) Exit Func ShowCross($start_x, $start_y, $end_x, $end_y, $width, $color) Local $hDC, $hPen, $obj_orig _GDIPlus_Startup() $hDC = _WinAPI_GetWindowDC(0) ; DC of entire screen (desktop) Local $hGraphics = _GDIPlus_GraphicsCreateFromHDC($hDC) Local $hPen = _GDIPlus_PenCreate($color, $width) Local $aDashes[3] = [2, 2 * $width, 1] _GDIPlus_PenSetDashArray($hPen, $aDashes) _GDIPlus_GraphicsDrawLine($hGraphics, $start_x, $start_y, $end_x, $end_y, $hPen) _WinAPI_BitBlt($hDC, $start_x, $start_y, $end_x - $start_x, $end_y - $start_x, $hGraphics, 0, 0, $SRCCOPY) ; clear resources _GDIPlus_GraphicsDispose($hGraphics) _WinAPI_ReleaseDC(0, $hDC) _GDIPlus_PenDispose($hPen) _GDIPlus_Shutdown() EndFunc ;==>ShowCross Func _GDIPlus_PenSetDashArray($hPen, $aDashes) Local $iI, $iCount, $tDashes, $pDashes, $aResult $iCount = $aDashes[0] $tDashes = DllStructCreate("float[" & $iCount & "]") $pDashes = DllStructGetPtr($tDashes) For $iI = 1 To $iCount DllStructSetData($tDashes, 1, $aDashes[$iI], $iI) Next $aResult = DllCall($ghGDIPDll, "uint", "GdipSetPenDashArray", "handle", $hPen, "ptr", $pDashes, "int", $iCount) If @error Then Return SetError(@error, @extended, False) Return $aResult[0] = 0 EndFunc Br, UEZ Edited May 18, 2011 by UEZ Please don't send me any personal message and ask for support! I will not reply! Selection of finest graphical examples at Codepen.io The own fart smells best! ✌Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!¯\_(ツ)_/¯ ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ 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