Inno.TLabel не отображается при использовании GDI + - PullRequest
0 голосов
/ 12 декабря 2018

Я пытаюсь использовать GDI + с Inno через DLL для сглаживания и других преимуществ.

Но я не могу использовать собственный Tnobel от Inno с DLL.При создании любого объекта через GDI +.TLabel не будет отображаться.Хотя я могу нарисовать TPanel, но TLabel, кажется, не работает вообще (показать).

Host ISS:

[Defines]
#define AppName "AppName"
#define AppVersion "0.1"
#define Color "$d03a1d"

[Setup]
AppName={#AppName}
AppVersion={#AppVersion}
DefaultDirName=./
Compression=none

[Code]
#define GDIDLLPATH "E:\Cpp\Projects\Build\build-GDI\build-GDI-msvc_x32-Release\MinimalGID.dll"

type
  ARGB = DWORD;

var
  l :TLabel;

function DrawRectangle(h : HWND; LineColor: ARGB;startX: integer;startY: integer; width,
       height: integer): integer;
  external 'DrawRectangle@{#GDIDLLPATH} stdcall delayload';
procedure  gdishutdown();
  external 'gdishutdown@{#GDIDLLPATH} stdcall delayload';

function Createlabel(hParent:TWInControl; hAutoSize,hWordwrap:Boolean;l,t,w,h:Integer; FSize,FColor:TColor;hCaption,hFontName:String;hAlignment: TAlignment):TLabel;
begin
  Result := TLAbel.Create(hParent);
  with Result do
  begin
    Parent:=hParent;
    AutoSize:=hAutoSize;
    SetBounds(l,t,w,h);
    WordWrap := hWordWrap;
    with Font do
    begin
      Name:= hFontName;
      Size:=Fsize;
      Color:=FColor;
    end;
    Alignment:=hAlignment;
    Caption:= hCaption;
    BringToFront;
  end;
end;

function CreateDefaultTxt(hParent :TWinControl; hLeft, hTop,hFontSize : Integer;hColor: TColor; hTxt : String): TLabel;
begin
  Result := Createlabel(hParent,true,false,hLeft,hTop,0,0,hFontSize,hColor,hTxt,'Segoe UI',taLeftJustify);
end;

procedure InitializeWizard();
begin
  with WizardForm do
  begin
    BorderStyle := bsNone;
    ClientWidth:=800;
    ClientHeight:=480;
    Center;
    OuterNotebook.Hide;
    InnerNotebook.Hide;
    Bevel.Hide;
    PageNameLabel.Hide;
    PageDescriptionLabel.Hide;
    MainPanel.Hide;
    BackButton.SetBounds(0,0,0,0);
    NextButton.SetBounds(0,0,0,0);
    CancelButton.SetBounds(0,0,0,0);
    DirBrowseButton.SetBounds(0,0,0,0);
    GroupBrowseButton.SetBounds(0,0,0,0);

    l  := CreateDefaultTxt(WizardForm,500,10,98,clRed,'Txt');
    DrawRectangle(Handle,$23000000,0,-6,Width,40);

  end;
end;

procedure DeinitializeSetup();
begin
  gdishutdown;
end;

TLabel будет корректно отображаться при удалении DrawRectangle ().

Моя DLL:

#include <Windows.h>
#include <gdiplus.h>
using namespace Gdiplus;
#include <objidl.h>
#pragma comment(lib, "Gdiplus.lib")

#include <functional>
#include <map>
#include <memory>
#include <vector>

#define DLL_EXPORT(RETURN_TYPE)                                                \
  extern "C" __declspec(dllexport) RETURN_TYPE __stdcall

class _GdiManager {
public:
  _GdiManager() {
    GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, nullptr);
  }
  void shutdown() { GdiplusShutdown(gdiplusToken); }

private:
  GdiplusStartupInput gdiplusStartupInput;
  ULONG_PTR gdiplusToken;
} GdiManager;

class DrawableObject {
public:
  virtual void draw(Gdiplus::Graphics &Graphics) = 0;
  virtual ~DrawableObject() = default;
};

namespace DrawableObjects {
class Rectangle : public DrawableObject {
public:
  Rectangle(ARGB Color, int X, int Y, int Width, int Height)
      : m_X{X}, m_Y{Y}, m_Width{Width}, m_Height{Height}, m_Brush{Color} {}
  void draw(Gdiplus::Graphics &graphics) override {
    graphics.FillRectangle(&m_Brush, m_X, m_Y, m_Width, m_Height);
  }

private:
  int m_X, m_Y, m_Width, m_Height;
  Gdiplus::SolidBrush m_Brush;
};

} // namespace DrawableObjects

LRESULT MasterWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);

class Painter {
public:
  Painter(HWND hWnd) : m_WindowHandle{hWnd}, m_Graphics{hWnd} {
    m_OriginalWindowProc = (WNDPROC)GetWindowLongW(m_WindowHandle, GWL_WNDPROC);
    SetWindowLongW(m_WindowHandle, GWL_WNDPROC, (LONG)MasterWindowProc);
  }

  ~Painter() {
    SetWindowLongW(m_WindowHandle, GWL_WNDPROC, (LONG)m_OriginalWindowProc);
  }

  LRESULT CallOriginalWndProc(HWND hwnd, UINT uMsg, WPARAM wParam,
                              LPARAM lParam) {
    return CallWindowProcW(m_OriginalWindowProc, hwnd, uMsg, wParam, lParam);
  }

  void Paint(LPPAINTSTRUCT ps) {
    for (auto &o : m_Objects)
      o->draw(m_Graphics);
  }

  std::vector<std::unique_ptr<DrawableObject>> &Objects() { return m_Objects; }

private:
  HWND m_WindowHandle;
  Gdiplus::Graphics m_Graphics;
  WNDPROC m_OriginalWindowProc;
  std::vector<std::unique_ptr<DrawableObject>> m_Objects;
};

std::map<HWND, std::unique_ptr<Painter>> windowPaint;

LRESULT MasterWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
  auto &p = windowPaint[hwnd];
  if (uMsg == WM_PAINT) {
    PAINTSTRUCT ps;
    BeginPaint(hwnd, &ps);
    p->Paint(&ps);
    EndPaint(hwnd, &ps);
  } else if (uMsg == WM_DESTROY)
    PostQuitMessage(0);
  return p->CallOriginalWndProc(hwnd, uMsg, wParam, lParam);
}

auto &insertPainter(HWND hwnd) {
  auto &my_painter = windowPaint[hwnd];
  if (!my_painter)
    my_painter = std::make_unique<Painter>(hwnd);
  return my_painter;
}

DLL_EXPORT(int)
DrawRectangle(HWND hwnd, ARGB LineColor, int startX, int startY, int width,
              int height) {
  auto &my_painter = insertPainter(hwnd);
  my_painter->Objects().push_back(std::make_unique<DrawableObjects::Rectangle>(
      LineColor, startX, startY, width, height));
  return 0;
}

DLL_EXPORT(void) gdishutdown() {
  windowPaint.clear();
  GdiManager.shutdown();
}

в DLLдля каждого Рисуемого объекта я фиксирую WndProc Родителя для рисования на WM_PAINT и вызываю его исходный WndProc после Рисования на WM_PAINT.Таким образом, мне не нужен хост для ручного захвата родительского WndProc для рисования

...