Reputation: 25928
Is it possible to paint to a Static control in NSIS? If it is how do I go about declaring variables such as a PAINTSTRUCT
and etc? I can do this easily in regular C but using NSIS and the assembly type language is throwing me.
Below I'm trying to draw a border on a static control:
Var MainWndSubProc
Function MainWndSubProc
${If} $2 = ${WM_DRAWITEM}
# I'm assuming $3 = the WPARAM and $4 = LPARAM?
$LOWORD $R0 $3 # get id of window we are painting
${If} $R0 == $myStaticId
# C code which works: how to translate to NSIS 'assembly'?
HDC hdc;
PAINTSTRUCT ps;
hdc = BeginPaint(args.hwnd, &ps);
RECT mRect;
GetClientRect(args.hwnd, &mRect);
HBRUSH brush = CreateSolidBrush(RGB(50, 50, 50));
HPEN pen = CreatePen(PS_SOLID, 5, RGB(191, 191, 191));
SelectObject(hdc, pen);
SelectObject(hdc, brush);
Rectangle(hdc, 0, 0, mRect.right, mRect.bottom);
DeleteObject(pen);
DeleteObject(brush);
EndPaint(args.hwnd, &ps);
# NSIS translation
# how to declare PAINTSTRUCT
$LOWORD $R0 $4
System::Call `user32::BeginPaint(i $R0, i R1)`
.. ?
${EndIf}
${EndIf}
FunctionEnd
Function MyGUIInit
${WndSubclass_Subclass} $HWNDPARENT MainWndSubProc $MainWndSubProc $MainWndSubProc
FunctionEnd
Upvotes: 0
Views: 147
Reputation: 101569
Types <= 64-bit are stored as strings in normal NSIS variables. For larger types you need to use the system plug-in struct syntax:
OutFile test.exe
RequestExecutionLevel user
Page InstFiles
!include WinMessages.nsh
!include nsDialogs.nsh
!include LogicLib.nsh
!include Colors.nsh
!include WndSubclass.nsh
Var MainWndSubProc
Var hStaticCtrl
Function MainWndSubProc
${If} $2 = ${WM_DRAWITEM}
System::Call '*$4(i,i,i,i,i,i.r5,i.r6,i,i,i.r8,i.r9)' ; Get HWND, HDC and size from DRAWITEMSTRUCT
${If} $hStaticCtrl = $5
System::Call 'GDI32::CreateSolidBrush(i 0x2277ee)i.s' ; Just made up a color here
System::Call 'GDI32::SelectObject(ir6,is)i.s'
${RGB} $7 191 191 191
System::Call 'GDI32::CreatePen(i${PS_SOLID}, i5, i "0x$7")i.s'
System::Call 'GDI32::SelectObject(ir6,is)i.s'
System::Call 'GDI32::Rectangle(ir6, i0, i0, ir8, ir9)'
System::Call 'GDI32::SelectObject(ir6,is)i.s'
System::Call 'GDI32::DeleteObject(is)'
System::Call 'GDI32::SelectObject(ir6,is)i.s'
System::Call 'GDI32::DeleteObject(is)'
${EndIf}
${EndIf}
FunctionEnd
Function .onGUIInit
; Your example failed to show how you create the static control so I'm forced to just create one here at run-time
GetDlgItem $0 $hwndparent 2 ; Find cancel button so we can put our control there
ShowWindow $0 0
System::Call '*(i,i,i,i)i.r1'
System::Call 'USER32::GetWindowRect(ir0,ir1)'
System::Call 'USER32::MapWindowPoints(i0,i$hwndparent,ir1,i2)'
System::Call '*$1(i.r4,i.r5,i.r6,i.r7)'
System::Free $1
IntOp $6 $6 - $4
IntOp $7 $7 - $5
System::Call 'USER32::CreateWindowEx(i0, t "Static", i0, i${WS_CHILD}|${WS_VISIBLE}|${SS_OWNERDRAW}, ir4, ir5, ir6, ir7, i$hwndparent, i0, i0, i0)i.r0'
StrCpy $hStaticCtrl $0
${WndSubclass_Subclass} $HWNDPARENT MainWndSubProc $MainWndSubProc $MainWndSubProc
FunctionEnd
Section
SectionEnd
The quality of your C code leads me to believe that you are not ready to write this kind of code. If you look at the documentation for DRAWITEMSTRUCT you will see this comment for the hDC member: "this device context must be used when performing drawing operations on the control." but you decided to call BeginPaint
! You also fail to restore the DC and you delete objects that are selected into a DC and that is not allowed.
Upvotes: 1