summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Wey2011-12-30 18:39:25 +0100
committerMike Wey2011-12-30 18:39:25 +0100
commit23a4423c025c42fc5131e090afe0df11112443df (patch)
tree77b0ddff2a4adb43f0ef2f3b3ae7d602506bfb1e
parentc227153d3ff409a94bce49542da85ab0706daa09 (diff)
Add the windows display functionality.
-rw-r--r--dmagick/Image.d35
-rw-r--r--dmagick/internal/Windows.d207
-rw-r--r--examples/draw.d2
-rw-r--r--windows.mak4
4 files changed, 215 insertions, 33 deletions
diff --git a/dmagick/Image.d b/dmagick/Image.d
index a556fa0..6f1a8e4 100644
--- a/dmagick/Image.d
+++ b/dmagick/Image.d
@@ -25,6 +25,8 @@ import dmagick.ImageView;
import dmagick.Options;
import dmagick.Utils;
+version(Windows) import dmagick.internal.Windows;
+
//Import all translated c headers.
import dmagick.c.MagickCore;
@@ -1180,37 +1182,8 @@ class Image
{
version(Windows)
{
- WNDCLASS wndclass;
- HINSTANCE hInstance = cast(HINSTANCE) GetModuleHandle(null);
- HWND hwnd;
- MSG msg;
-
- wndclass.style = CS_HREDRAW | CS_VREDRAW;
- wndclass.lpfnWndProc = &WndProc;
- wndclass.cbClsExtra = 0;
- wndclass.cbWndExtra = 0;
- wndclass.hInstance = hInstance;
- wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
- wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
- wndclass.hbrBackground = null;
- wndclass.lpszMenuName = "DMagick"w;
- wndclass.lpszClassName = "DMagick"w;
-
- if (!RegisterClass(&wndclass))
- throw new DMagickException("This program requires Windows NT!");
-
- hwnd = CreateWindow(cn, toStringz(title), WS_OVERLAPPEDWINDOW,
- CW_USEDEFAULT, CW_USEDEFAULT, width, height,
- null, null, hInstance, null);
-
- ShowWindow(hwnd, SW_SHOWNORMAL);
- UpdateWindow(hwnd);
-
- while (GetMessage(&msg, NULL, 0, 0))
- {
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }
+ Window win = new Window(this);
+ win.display();
}
else
{
diff --git a/dmagick/internal/Windows.d b/dmagick/internal/Windows.d
new file mode 100644
index 0000000..1358253
--- /dev/null
+++ b/dmagick/internal/Windows.d
@@ -0,0 +1,207 @@
+/**
+ * Copyright: Mike Wey 2011
+ * License: zlib (See accompanying LICENSE file)
+ * Authors: Mike Wey
+ */
+
+module dmagick.internal.Windows;
+
+import core.sys.windows.windows;
+
+import dmagick.Image;
+import dmagick.Exception;
+import dmagick.Geometry;
+
+Window[HWND] windows;
+
+class Window
+{
+ Image image;
+ size_t height;
+ size_t width;
+
+ WNDCLASS wndclass;
+ HINSTANCE hInstance;
+ HWND hwnd;
+ MSG msg;
+
+ this(Image image)
+ {
+ this.image = image;
+
+ height = image.rows;
+ width = image.columns;
+
+ hInstance = cast(HINSTANCE) GetModuleHandleA(null);
+
+ wndclass.style = CS_HREDRAW | CS_VREDRAW;
+ wndclass.lpfnWndProc = &WndProc;
+ wndclass.cbClsExtra = 0;
+ wndclass.cbWndExtra = 0;
+ wndclass.hInstance = hInstance;
+ wndclass.hIcon = LoadIconA(null, IDI_APPLICATION);
+ wndclass.hCursor = LoadCursorA(null, IDC_ARROW);
+ wndclass.hbrBackground = null;
+ wndclass.lpszMenuName = "DMagick";
+ wndclass.lpszClassName = "DMagick";
+
+ if (!RegisterClassA(&wndclass))
+ throw new DMagickException("This program requires Windows NT!");
+
+ RECT rect = RECT(0,0, width,height);
+ AdjustWindowRect(&rect, WS_OVERLAPPEDWINDOW, false);
+
+ hwnd = CreateWindowA("DMagick", "DMagick", WS_OVERLAPPEDWINDOW,
+ CW_USEDEFAULT, CW_USEDEFAULT, rect.right-rect.left, rect.bottom-rect.top,
+ null, null, hInstance, null);
+
+ windows[hwnd] = this;
+ }
+
+ void display()
+ {
+ ShowWindow(hwnd, SW_SHOWNORMAL);
+ UpdateWindow(hwnd);
+
+ while (GetMessageA(&msg, null, 0, 0))
+ {
+ TranslateMessage(&msg);
+ DispatchMessageA(&msg);
+ }
+ }
+
+ extern(Windows) static LRESULT WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
+ {
+ static int cxClient, cyClient, cxSource, cySource;
+ int x, y;
+ HDC hdc;
+ PAINTSTRUCT ps;
+
+ static HDC hdcMem;
+ static HBITMAP hbmMem;
+ static HANDLE hOld;
+ RECT rect;
+
+ switch (message)
+ {
+ case WM_SIZE:
+ cxClient = LOWORD(lParam);
+ cyClient = HIWORD(lParam);
+ return 0;
+
+ case WM_ERASEBKGND: // don't redraw bg
+ return 1;
+
+ case WM_PAINT:
+ {
+ // Get DC for window
+ hdc = BeginPaint(hwnd, &ps);
+
+ // Create an off-screen DC for double-buffering
+ hdcMem = CreateCompatibleDC(hdc);
+ hbmMem = CreateCompatibleBitmap(hdc, cxClient, cyClient);
+ hOld = SelectObject(hdcMem, hbmMem);
+
+ // Draw into hdcMem
+ GetClientRect(hwnd, &rect);
+ FillRect(hdcMem, &rect, GetStockObject(BLACK_BRUSH));
+
+ windows[hwnd].DrawAlphaBlend(hwnd, hdcMem);
+
+ // Transfer the off-screen DC to the screen
+ BitBlt(hdc, 0, 0, cxClient, cyClient, hdcMem, 0, 0, SRCCOPY);
+
+ // Free-up the off-screen DC
+ SelectObject(hdcMem, hOld);
+ DeleteObject(hbmMem);
+ DeleteDC (hdcMem);
+
+ EndPaint(hwnd, &ps);
+ return 0;
+ }
+
+ case WM_DESTROY:
+ windows[hwnd] = null;
+ PostQuitMessage(0);
+ return 0;
+
+ default:
+ }
+
+ return DefWindowProcA(hwnd, message, wParam, lParam);
+ }
+
+ void DrawAlphaBlend(HWND hWnd, HDC hdcwnd)
+ {
+ HDC hdc; // handle of the DC we will create
+ HBITMAP hbitmap; // bitmap handle
+ BITMAPINFO bmi; // bitmap header
+ VOID* pvBits; // pointer to DIB section
+ ULONG ulWindowWidth, ulWindowHeight; // window width/height
+ RECT rt; // used for getting window dimensions
+
+ // get window dimensions
+ GetClientRect(hWnd, &rt);
+
+ // calculate window width/height
+ ulWindowWidth = rt.right - rt.left;
+ ulWindowHeight = rt.bottom - rt.top;
+
+ // make sure we have at least some window size
+ if (ulWindowWidth < 1 || ulWindowHeight < 1)
+ return;
+
+ // create a DC for our bitmap -- the source DC for GdiAlphaBlend
+ hdc = CreateCompatibleDC(hdcwnd);
+
+ // setup bitmap info
+ bmi.bmiHeader.biSize = BITMAPINFOHEADER.sizeof;
+ bmi.bmiHeader.biWidth = width;
+ bmi.bmiHeader.biHeight = -height; // must be inverted so Y axis is at top
+ bmi.bmiHeader.biPlanes = 1;
+ bmi.bmiHeader.biBitCount = 32; // four 8-bit components
+ bmi.bmiHeader.biCompression = BI_RGB;
+ bmi.bmiHeader.biSizeImage = width * height * 4;
+
+ // create our DIB section and select the bitmap into the dc
+ hbitmap = CreateDIBSection(hdc, &bmi, DIB_RGB_COLORS, &pvBits, null, 0x0);
+ SelectObject(hdc, hbitmap);
+
+ auto area = Geometry(width, height, 0, 0);
+ enum channels = "BGRA"; // win32 uses BGR(A)
+ byte[] arr = (cast(byte*)pvBits)[0 .. (area.width * area.height) * channels.length];
+ image.exportPixels(area, arr, channels);
+
+ //TODO: Rezize image.
+ BitBlt(hdcwnd, 0, 0, width, height, hdc, 0, 0, SRCCOPY);
+
+ DeleteObject(hbitmap);
+ DeleteDC(hdc);
+ }
+}
+
+pragma(lib, "gdi32.lib");
+
+const AC_SRC_OVER = 0x00;
+const AC_SRC_ALPHA = 0x01;
+const GWLP_USERDATA = -21;
+
+enum DWORD BI_RGB = 0;
+enum UINT DIB_RGB_COLORS = 0;
+
+struct BLENDFUNCTION
+{
+ BYTE BlendOp;
+ BYTE BlendFlags;
+ BYTE SourceConstantAlpha;
+ BYTE AlphaFormat;
+}
+
+struct AlphaBlendType
+{
+ static normal = BLENDFUNCTION(AC_SRC_OVER, 0, 255, AC_SRC_ALPHA);
+}
+
+extern(Windows) BOOL BitBlt(HDC, int, int, int, int, HDC, int, int, DWORD);
+extern(Windows) HBITMAP CreateCompatibleBitmap(HDC, int, int);
+extern(Windows) HBITMAP CreateDIBSection(HDC, const(BITMAPINFO)*, UINT, void**, HANDLE, DWORD); \ No newline at end of file
diff --git a/examples/draw.d b/examples/draw.d
index deed525..0aced61 100644
--- a/examples/draw.d
+++ b/examples/draw.d
@@ -64,7 +64,7 @@ void main()
dc.fill(cylinderTop);
dc.roundRectangle(progressXmax - (2 * wc), progressYmin, progressXmax, progressYmax, wc, hc);
- dc.font("Helvetica");
+ dc.font("Arial");
dc.fontSize(fontsize);
dc.stroke(textShadow);
dc.fill(textColor);
diff --git a/windows.mak b/windows.mak
index ebf57c1..5b0edeb 100644
--- a/windows.mak
+++ b/windows.mak
@@ -108,7 +108,9 @@ SOURCE= \
dmagick\c\type.d \
dmagick\c\utility.d \
dmagick\c\xmlTree.d \
- dmagick\c\xwindow.d
+ dmagick\c\xwindow.d \
+ \
+ dmagick\internal\Windows.d \
################## DOCS ####################################