2016-07-03 35 views
0

是否可以繪製到NSIS中的靜態控件?如果這是我如何去聲明變量,如PAINTSTRUCT等?我可以在普通的C中輕鬆地做到這一點,但使用NSIS和彙編類型語言正在拋出我。可能在NSIS中繪製窗口,如何聲明WinAPI類型的變量?

下面我想畫上一個靜態控件邊框:

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 
+0

通過他們的文檔挖掘我什麼都看不到,但他們的文檔網站確實有[幾個完整的安裝程序](http://nsis.sourceforge.net/Category:Real_World_Installers)可以做到這一點。 [WndSubclass](http://nsis.sourceforge.net/WndSubclass_plug-in)插件可能具有您需要的功能,但我懷疑它。所有的事情都是平等的,如果這是我的項目,我可能會寫一個插件來完成所有繁重的工作。 – theB

回答

1

類型< = 64位被存儲在正常NSIS變量字符串。對於較大的類型,您需要使用系統插件結構的語法:

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 

的C代碼的質量使我相信,你是不是準備寫這種代碼。如果您查看DRAWITEMSTRUCT的文檔,您將看到hDC成員的此評論:「在對控件執行繪圖操作時,將使用此設備上下文必須」。但你決定致電BeginPaint!您也無法恢復DC,並且刪除選中到DC中的對象,但這是不允許的。

+0

謝謝,是的,我從處理'WM_PAINT'而不是'WM_DRAWITEM'的WinAPI項目複製了我的代碼。重新釋放DC,是否也需要'WM_PAINT'? –

+0

重新進行靜態控制我將繪畫,它是一個現有的靜態控件'$ mui.WelcomePage.title'。我已經爲它添加了'SS_OWNERDRAWN'風格並使用WinSpy確認它成功。但它並沒有在這個控件上畫出邊界。任何想法可能是錯誤? –

+1

如果你調用一個函數來獲取它,你只需要釋放DC。如果有的話,您可能需要刪除其他SS_ *樣式。 – Anders