Я пытаюсь использовать 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 для рисования