AutoXenon Posted October 13, 2022 Posted October 13, 2022 (edited) expandcollapse popupDialog() GUI() Func Dialog() Local $hor = @DesktopWidth*2 Local $ver = @DesktopHeight*2 Local $intent = MsgBox(3,"","Customize crosshair size?") If $intent = 2 Then Exit If $intent = 6 Then $hor = InputBox("Width", "Enter width of crosshair", $hor) $ver = InputBox("Height", "Enter height of crosshair", $ver) If not (IsInt(Number($hor)) and IsInt(Number($ver)) and $hor>0 and $ver>0) Then MsgBox(0,"Invalid dimensions","Width and height must be positive integers.") Exit EndIf EndIf Local $widthInBytes = 2*ceiling(ceiling($hor/2)/8) Local $totBytes = $widthInBytes*$ver MsgBox(0,"Be Patient","This will take a few seconds to loop over " & $totBytes & " bytes. Press OK to start.") Global $hCursor = MakeXhair($hor,$ver) MsgBox(0,"Complete","Built a crosshair that is " & $hor & "x" & $ver & " large.") EndFunc Func GUI() GUICreate("test") Local $button_NORMAL = GUICtrlCreateButton("Set as normal arrow",0,0) Local $button_IBEAM = GUICtrlCreateButton("Set as text select",0,25) Local $button_HAND = GUICtrlCreateButton("Set as hyperlink hand",0,50) Local $button_APPSTARTING = GUICtrlCreateButton("Set as hourglass arrow",0,75) Local $button_HELP = GUICtrlCreateButton("Set as help arrow",0,100) Local $button_CROSS = GUICtrlCreateButton("Set as precision select",0,125) Local $button_rebuild = GUICtrlCreateButton("Rebuild crosshair",0,150) GUISetState() GUIRegisterMsg(0x0020, WM_SETCURSOR) Local $GuiMsg do $GuiMsg = GuiGetMsg() Switch $GuiMsg Case -3 Exit Case $button_NORMAL DllCall( "user32.dll" , "bool" , "SetSystemCursor" , "handle", CopyIcon($hCursor) , "dword" , 32512 ) Case $button_HAND DllCall( "user32.dll" , "bool" , "SetSystemCursor" , "handle", CopyIcon($hCursor) , "dword" , 32649 ) Case $button_HELP DllCall( "user32.dll" , "bool" , "SetSystemCursor" , "handle", CopyIcon($hCursor) , "dword" , 32651 ) Case $button_APPSTARTING DllCall( "user32.dll" , "bool" , "SetSystemCursor" , "handle", CopyIcon($hCursor) , "dword" , 32650 ) Case $button_CROSS DllCall( "user32.dll" , "bool" , "SetSystemCursor" , "handle", CopyIcon($hCursor) , "dword" , 32515 ) Case $button_IBEAM DllCall( "user32.dll" , "bool" , "SetSystemCursor" , "handle", CopyIcon($hCursor) , "dword" , 32513 ) Case $button_rebuild DllCall( "user32.dll" , "bool" , "DestroyCursor" , $hCursor ) Dialog() EndSwitch until 0 EndFunc ; | AND mask value | XOR mask value | Result displayed | ; |----------------|----------------|----------------------------------| ; | 0 | 0 | Pixel is black | ; | 0 | 1 | Pixel is white | ; | 1 | 0 | Pixel is unchanged (transparent) | ; | 1 | 1 | Pixel color is inverted | Func MakeXhair($hor,$ver) Local $widthInBytes = 2*ceiling(ceiling($hor/2)/8) Local $totBytes = $widthInBytes*$ver Local $curAND = DllStructCreate("byte[" & $totBytes & "]") Local $curXOR = DllStructCreate("byte[" & $totBytes & "]") Local $and , $xor Local $xByteCenter1Based = ceiling((int($hor/2)+1)/8) Local $ctrShift = int($hor/2) - 8*($xByteCenter1Based-1) Local $edgShift = 8*ceiling($hor/8)-$hor For $i = 1 to $ver For $j = 1 to ceiling($hor/8) $and = 0xff $xor = 0x00 If $j = $xByteCenter1Based Then $xor = BitShift( 0x80 ,$ctrShift) ; $and = 255-BitShift( 0x80 ,$ctrShift) EndIf If $i = int($ver/2)+1 Then $xor = ( $j=ceiling($hor/8) ? Round(exp($edgShift*log(2))*Int(255*exp(-$edgShift*log(2)))) : 0xff ) ; $and = ( $j=ceiling($hor/8) ? 255-Round(exp($edgShift*log(2))*Int(255*exp(-$edgShift*log(2)))) : 0x00 ) EndIf DllStructSetData( $curAND , 1 , $and , $j+$widthInBytes*($i-1) ) DllStructSetData( $curXOR , 1 , $xor , $j+$widthInBytes*($i-1) ) Next If Mod(ceiling($hor/8),2)<>0 Then DllStructSetData( $curAND , 1 , 0xff , $i*$widthInBytes ) DllStructSetData( $curXOR , 1 , 0x00 , $i*$widthInBytes ) EndIf Next Local $andMaskPtr = DllStructGetPtr($curAnd), $xorMaskPtr = DllStructGetPtr($curXor) Return CreateCursor(Null, int($hor/2), int($ver/2), 8*$widthInBytes, $ver, $andMaskPtr, $xorMaskPtr) EndFunc Func CreateCursor($hInst, $xHotSpot, $yHotSpot, $nWidth, $nHeight, $pvANDPlane, $pvXORPlane) Local $aCall = DllCall("user32.dll", "handle", "CreateCursor", _ "handle", $hInst, _ "int", $xHotSpot, _ "int", $yHotSpot, _ "int", $nWidth, _ "int", $nHeight, _ "ptr", $pvANDPlane, _ "ptr", $pvXORPlane) Return $aCall[0] EndFunc Func CopyIcon($handle) Local $aCall = DllCall("user32.dll", "handle", "CopyIcon", "handle", $handle ) Return $aCall[0] EndFunc Func WM_SETCURSOR($hWnd, $iMsg, $wParam, $lParam) Local Static $dll = DllOpen("user32.dll") DllCall( $dll , "handle" , "SetCursor" , "handle" , $hCursor ) Return True EndFunc Edited October 15, 2022 by AutoXenon
AutoXenon Posted October 15, 2022 Author Posted October 15, 2022 Significant point about this demonstration is that the size can far exceed the 32x32 cursor size limitation, even as far as quadruple the actual size of your screenbuffer.
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