2016-07-03 1 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 변수에서 문자열로 저장됩니다. C 코드의 품질은 당신이 이러한 종류의 코드를 쓸 준비가되지 않은 것을 믿고 날 리드

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 

: 큰 유형의 당신은 플러그인 구조체 구문 시스템을 사용해야합니다. DRAWITEMSTRUCT 설명서를 보면 hDC 멤버에 대한이 주석이 표시됩니다. "이 장치 컨텍스트 은 컨트롤에서 드로잉 작업을 수행 할 때을 사용해야합니다." 하지만 BeginPaint에 전화하기로 결정했습니다. 또한 DC를 복원하지 못하고 DC로 선택되어 허용되지 않는 개체를 삭제합니다.

+0

감사합니다. 예, WinAPI 프로젝트에서 WM_DRAWITEM이 아니라 WM_PAINT를 처리하는 코드를 복사했습니다. DC를 다시 릴리스하는 것은'WM_PAINT'에서도 필요합니까? –

+0

정적 컨트롤을 다시 그리기 위해, 기존의 정적 컨트롤'$ mui.WelcomePage.title'. 나는'SS_OWNERDRAWN' 스타일을 추가하고 WinSpy를 사용하여 성공했는지 확인했다. 하지만이 컨트롤에 국경을 그리지는 않습니다. 어떤 생각이 오류 일 수 있습니까? –

+1

먼저 DC를 가져 오려면 먼저 함수를 호출하면됩니다. 있다면 다른 SS_ * 스타일을 제거해야 할 수도 있습니다. – Anders