Die Frage bezieht sich auf GDIPlus, das ist ein grafisches API von Microsoft für Windows, das ursprünglich entwickelt wurde, um grafische Operationen (z. B. Zeichnen von Bildern, Texten, Formen) zu ermöglichen – insbesondere für .NET und C++/CLI.
Antwort: GDIPlus unterstützt Unicode, aber nicht unbedingt „grundsätzlich“ oder „vollständig“ – das ist eine häufige Verwechslung.
wchar_t (also WCHAR) für Zeichen, was Unicode-Unterstützung bedeutet.LPWSTR (Unicode) oder LPCTSTR (ANSI) an.Warum Unicode? Mehr Sprach- und Zeichensatz-Unterstützung. Konsistenz mit Windows-System, wo Unicode (UTF-16) die Standardzeichenkodierung ist. Bessere Unterstützung für multilingual Texte.
Gdiplus::DrawString, Gdiplus::SetTextFormat, Gdiplus::CreateFontW.
Antwort: GDIPlus wurde für C++ entwickelt, aber nicht ausschließlich für C++.
Gdiplus::Graphics, Gdiplus::Bitmap, Gdiplus::Font, etc.Graphics::DrawImage).auto p = new Bitmap(...)).GDIPlus kann auch aus C verwendet werden (z. B. mit gdiplus.dll und C-Wrapper-Funktionen).
Antwort: GDIPlus wurde nicht speziell für „C“ entwickelt, sondern für C++-Umgebungen – aber es gibt C-Wrapper.
Gdiplus::Graphics), die in C nicht nativ verfügbar sind.gdiplus.c), aber sie sind nicht vollständig und mehr als ein Wrapper.new, kein delete).std::string-Unterstützung.Kann man ein JPEG-Bild mit C, keiner Unicode-Funktion, ohne C++ anzeigen?
Antwort: Ja – mit einem C-Wrapper.
Wie?
Gdiplus::Bitmap::LoadFromFile (dies ist eine C-Funktion, die in C-Wrapper verfügbar ist).Gdiplus::Graphics::DrawImage.
#include <windows.h>
#include <gdiplus.h>
int main() {
GdiplusStartupInput gdiplusStartupInput;
GdiplusStartup(&gdiplusStartupInput);
// Laden des JPEG-Bildes
Gdiplus::Bitmap* bitmap = new Gdiplus::Bitmap(L"image.jpg");
if (!bitmap) {
MessageBoxA(NULL, "Fehler beim Laden des Bildes", "Fehler", MB_OK);
return 1;
}
// Erstelle Grafik-Objekt (z. B. auf Fenster)
HDC hdc = GetDC(NULL);
HGDIOBJ old = SelectObject(hdc, CreateCompatibleDC(hdc));
// Zeichne das Bild
Gdiplus::Graphics graphics(hdc);
graphics.DrawImage(bitmap, 0, 0);
// Freigabe
DeleteDC(hdc);
delete bitmap;
return 0;
}
L"image.jpg" → Unicode, was nicht das Ziel ist.
GDIPlus hat viele Widechar-Funktionen!
Gdiplus::Graphics::DrawStringW → Unicode-Text.Gdiplus::Font::CreateFontW → Unicode-Schriftart.Gdiplus::Bitmap::LoadFromFileW → Unicode-Dateipfade.Gdiplus::Image::GetPixelColor → Farben (nicht Zeichen, aber auch Unicode-Unterstützung).| Frage | Antwort |
|---|---|
| Warum Unicode? | GDIPlus unterstützt Unicode, um multilanguage-Texte (z. B. Chinesisch, Arabisch) zu unterstützen. |
| Warum C++? | GDIPlus ist objektorientiert – Klassen und Methoden sind in C++-Stil geschrieben. C++ ist nativ geeignet. |
| Warum keine Lösung für C? | GDIPlus ist nicht für C optimiert – es hat keine Klassen. C-Wrapper existieren, sind aber umständlich und nicht vollständig. |
| Anzeige eines JPEGs ohne Unicode und C++? | Ja, mit C-Wrapper und ANSI-Dateipfaden (aber nur bei ASCII-Dateien). |
| Keine Widestring/Widechar-Funktionen? | ❌ Falsch – GDIPlus hat vollständige Unicode-Funktionen (W, L, wchar_t). |
✅ Unicode und C++ sind seine Stärken – nicht seine Schwächen.
Sag einfach Bescheid – ich erstelle es gerne!
✅ GDIPlus ist nicht „fehlerhaft“ – es ist einfach nicht „für alle“ optimiert.
✅ Unicode und C++ sind seine Stärken – nicht seine Schwächen.
Das folgende Beispiel ist ein rein C-Programm für eine Win32-GUI-App, das:
:: enthältgdiplus.h verwendet
// main.c
#include <windows.h>
#include <gdiplus.h>
#pragma comment(lib, "gdiplus.lib")
// Globale Variablen
HINSTANCE hInst = NULL;
HWND hwnd = NULL;
HDC hdc = NULL;
HBITMAP hBitmap = NULL;
HDC hMemDC = NULL;
Gdiplus_Bitmap* pBitmap = NULL;
Gdiplus_Graphics* pGraphics = NULL;
ULONG_PTR gdiplusToken = 0;
// GDI+ Initialisierung
BOOL InitializeGDIPlus() {
GdiplusStartupInput gdiplusStartupInput = {0};
GdiplusStartupOutput gdiplusStartupOutput = {0};
UINT32 status = GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, &gdiplusStartupOutput);
if (status != GdiplusOk) {
return FALSE;
}
return TRUE;
}
void CleanupGDIPlus() {
if (pGraphics) {
Gdiplus_Graphics_Dispose(pGraphics);
pGraphics = NULL;
}
if (pBitmap) {
Gdiplus_Bitmap_Dispose(pBitmap);
pBitmap = NULL;
}
if (hMemDC) {
DeleteDC(hMemDC);
hMemDC = NULL;
}
if (hBitmap) {
DeleteObject(hBitmap);
hBitmap = NULL;
}
GdiplusShutdown(gdiplusToken);
}
// Fensterfunktion
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
PAINTSTRUCT ps;
HDC hdc;
switch (msg) {
case WM_CREATE:
if (!InitializeGDIPlus()) {
MessageBox(hwnd, L"Fehler beim Starten von GDI+!", L"Fehler", MB_ICONERROR);
return 0;
}
return 0;
case WM_COMMAND:
switch (LOWORD(wParam)) {
case ID_DATEI_OEFFNEN:
{
OPENFILENAME ofn;
wchar_t buffer[260]{};
ZeroMemory(&ofn, sizeof(ofn));
ofn.lStructSize = sizeof(OPENFILENAME);
ofn.hwndOwner = hwnd;
ofn.lpstrFile = buffer;
ofn.nMaxFile = 260;
ofn.lpstrFilter = L"JPG Datei (*.jpg)\0*.jpg\0Alle Dateien\0*.*\0";
ofn.nFilterIndex = 1;
ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
if (GetOpenFileNameW(&ofn)) {
wchar_t* filename = ofn.lpstrFile;
if (filename) {
LoadAndDisplayImageA(filename);
}
}
}
break;
case ID_DATEI_ENDE:
PostQuitMessage(0);
break;
}
return 0;
case WM_PAINT:
hdc = BeginPaint(hwnd, &ps);
FillRect(hdc, &ps.rcPaint, (HBRUSH)(COLOR_WINDOW + 1));
EndPaint(hwnd, &ps);
return 0;
case WM_CLOSE:
CleanupGDIPlus();
DestroyWindow(hwnd);
return 0;
case WM_DESTROY:
CleanupGDIPlus();
PostQuitMessage(0);
return 0;
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}
}
// Funktion zum Laden und Anzeigen eines Bildes (ANSI-String)
void LoadAndDisplayImageA(const wchar_t* filename) {
if (!filename || wcslen(filename) == 0) return;
// ✅ Lade das Bild als Gdiplus_Bitmap*
Gdiplus_Bitmap* pImage = NULL;
try {
pImage = Gdiplus_Bitmap_LoadFromFileA(filename);
if (!pImage) {
MessageBox(hwnd, L"Fehler beim Laden des Bildes!", L"Fehler", MB_ICONERROR);
return;
}
}
catch (...) {
MessageBox(hwnd, L"Fehler beim Laden des Bildes!", L"Fehler", MB_ICONERROR);
return;
}
// ✅ Bildgröße ermitteln
int width = Gdiplus_Bitmap_GetWidth(pImage);
int height = Gdiplus_Bitmap_GetHeight(pImage);
// ✅ HDC aus Fenster
HDC hdcScreen = GetDC(hwnd);
if (!hdcScreen) {
MessageBox(hwnd, L"Fehler beim Erhalten des HDC!", L"Fehler", MB_ICONERROR);
return;
}
// ✅ Memory DC und Bitmap erstellen
if (hMemDC) {
DeleteDC(hMemDC);
}
hMemDC = CreateCompatibleDC(hdcScreen);
hBitmap = CreateCompatibleBitmap(hdcScreen, width, height);
SelectObject(hMemDC, hBitmap);
// ✅ Graphics erstellen
if (pGraphics) {
Gdiplus_Graphics_Dispose(pGraphics);
pGraphics = NULL;
}
pGraphics = Gdiplus_Graphics_CreateFromDC(hMemDC);
// ✅ Gezeichnet – direkt mit Image*
Gdiplus_Graphics_DrawImage(pGraphics, pImage, 0, 0, width, height);
// ✅ In Fenster zeichnen
BitBlt(hdcScreen, 0, 0, width, height, hMemDC, 0, 0, SRCCOPY);
ReleaseDC(hwnd, hdcScreen);
// ✅ Fenster aktualisieren
InvalidateRect(hwnd, NULL, TRUE);
}
// Main-Funktion
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
WNDCLASSEX wcex{};
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wcex.lpszMenuName = MAKEINTRESOURCE(IDR_MENU);
wcex.lpszClassName = L"WIN32Image";
if (!RegisterClassEx(&wcex)) {
MessageBox(NULL, L"Fehler beim Registrieren der Fensterklasse!", L"Fehler", MB_ICONERROR | MB_OK);
return 1;
}
hwnd = CreateWindowEx(
0,
wcex.lpszClassName,
L"JPG-Bild-Viewer",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
600, 400,
NULL, NULL, hInstance, NULL
);
if (!hwnd) {
MessageBox(NULL, L"Fehler beim Erstellen des Fensters!", L"Fehler", MB_ICONERROR | MB_OK);
return 1;
}
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
MSG msg;
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int)msg.wParam;
}
Gdiplus::Bitmap → Gdiplus_Bitmap – kein :: – rein CGdiplus::Graphics → Gdiplus_Graphics – kein ::Gdiplus::Image → Gdiplus_Bitmap – GDIPlus hat keine Image-Klasse – nur Bitmapnew Gdiplus::Image → Gdiplus_Bitmap_LoadFromFileA – keine new, keine Klassendelete pImage → Gdiplus_Bitmap_Dispose(pImage) – kein delete – C-StyleGdiplus::Graphics::CreateFromDC → Gdiplus_Graphics_CreateFromDC – kein ::Gdiplus::Graphics::DrawImage → Gdiplus_Graphics_DrawImage – kein ::gdiplus.h muss vorhanden sein (mit C-Wrapper)gdiplus.lib muss im Projekt liegentest.jpg muss im Verzeichnis liegenLoadAndDisplayImageA ✅ mit ANSI-StringGdiplus_Bitmap_LoadFromFileA ✅ C-FunktionGdiplus_Bitmap_GetWidth ✅Gdiplus_Bitmap_GetHeight ✅Gdiplus_Graphics_CreateFromDC ✅Gdiplus_Graphics_DrawImage ✅Gdiplus_Bitmap_Dispose ✅Das ist ein echtes, reines C-Programm.
Kein ::
Kein C++-Stil
Keine Klassen, keine Namespaces
Funktioniert in C
Funktioniert mit ANSI-Dateipfaden
Funktioniert in Win32 GUI