From 1784a073900bfcafdb6d2699364cfc84528adabb Mon Sep 17 00:00:00 2001 From: Pietro Gagliardi Date: Sat, 11 Oct 2014 12:11:56 -0400 Subject: Moved the Windows Popover stuff out of the way and renamed its folder to just popover/; I'll continue the GTK+ experiments here. --- popover/main_windows.c | 245 +++++++++++++++++++++++++++++++++++++++++++++++ popover/popover.c | 174 +++++++++++++++++++++++++++++++++ popover/popover.h | 30 ++++++ windowspopover/main.c | 245 ----------------------------------------------- windowspopover/popover.c | 174 --------------------------------- windowspopover/popover.h | 30 ------ 6 files changed, 449 insertions(+), 449 deletions(-) create mode 100644 popover/main_windows.c create mode 100644 popover/popover.c create mode 100644 popover/popover.h delete mode 100644 windowspopover/main.c delete mode 100644 windowspopover/popover.c delete mode 100644 windowspopover/popover.h diff --git a/popover/main_windows.c b/popover/main_windows.c new file mode 100644 index 0000000..0bf368f --- /dev/null +++ b/popover/main_windows.c @@ -0,0 +1,245 @@ +// 9 october 2014 +#define UNICODE +#define _UNICODE +#define STRICT +#define STRICT_TYPED_ITEMIDS +// get Windows version right; right now Windows XP +#define WINVER 0x0501 +#define _WIN32_WINNT 0x0501 +#define _WIN32_WINDOWS 0x0501 /* according to Microsoft's winperf.h */ +#define _WIN32_IE 0x0600 /* according to Microsoft's sdkddkver.h */ +#define NTDDI_VERSION 0x05010000 /* according to Microsoft's sdkddkver.h */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "popover.h" + +// #qo LIBS: user32 kernel32 gdi32 + +// TODO +// - should the parent window appear deactivated? + +HWND popoverWindow; + +void xpanic(char *msg, DWORD err) +{ + printf("%d | %s\n", err, msg); + abort(); +} + +popover *p; + +HRGN makePopoverRegion(HDC dc, LONG width, LONG height) +{ + popoverPoint ppt[20]; + POINT pt[20]; + int i, n; + HRGN region; + + n = popoverMakeFramePoints(p, (intptr_t) width, (intptr_t) height, ppt); + for (i = 0; i < n; i++) { + pt[i].x = (LONG) (ppt[i].x); + pt[i].y = (LONG) (ppt[i].y); + } + + if (BeginPath(dc) == 0) + xpanic("error beginning path for Popover shape", GetLastError()); + if (Polyline(dc, pt, n) == 0) + xpanic("error drawing lines in Popover shape", GetLastError()); + if (EndPath(dc) == 0) + xpanic("error ending path for Popover shape", GetLastError()); + region = PathToRegion(dc); + if (region == NULL) + xpanic("error converting Popover shape path to region", GetLastError()); + return region; +} + +#define msgPopoverPrepareLeftRight (WM_APP+50) +#define msgPopoverPrepareTopBottom (WM_APP+51) + +LRESULT CALLBACK popoverproc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + PAINTSTRUCT ps; + HDC dc; + HRGN region; + RECT r; + LONG width; + LONG height; + WINDOWPOS *wp; + HBRUSH brush; + + switch (uMsg) { + case WM_NCPAINT: + if (GetWindowRect(hwnd, &r) == 0) + xpanic("error getting Popover window rect for shape redraw", GetLastError()); + width = r.right - r.left; + height = r.bottom - r.top; + dc = GetWindowDC(hwnd); + if (dc == NULL) + xpanic("error getting Popover window DC for drawing border", GetLastError()); + region = makePopoverRegion(dc, width, height); + // don't call FillRgn(); WM_ERASEBKGND seems to do this to the non-client area for us already :S (TODO confirm) + // TODO arrow is black in wine + brush = (HBRUSH) GetStockObject(BLACK_BRUSH); + if (brush == NULL) + xpanic("error getting Popover border brush", GetLastError()); + if (FrameRgn(dc, region, brush, 1, 1) == 0) + xpanic("error drawing Popover border", GetLastError()); + if (DeleteObject(region) == 0) + xpanic("error deleting Popover shape region", GetLastError()); + if (ReleaseDC(hwnd, dc) == 0) + xpanic("error releasing Popover window DC for shape drawing", GetLastError()); + return 0; + case WM_WINDOWPOSCHANGED: + // this must be here; if it's in WM_NCPAINT weird things happen (see http://stackoverflow.com/questions/26288303/why-is-my-client-rectangle-drawing-behaving-bizarrely-pictures-provided-if-i-t) + wp = (WINDOWPOS *) lParam; + if ((wp->flags & SWP_NOSIZE) == 0) { + dc = GetWindowDC(hwnd); + if (dc == NULL) + xpanic("error getting Popover window DC for reshaping", GetLastError()); + region = makePopoverRegion(dc, wp->cx, wp->cy); + if (SetWindowRgn(hwnd, region, TRUE) == 0) + xpanic("error setting Popover shape", GetLastError()); + // don't delete the region; the window manager owns it now + if (ReleaseDC(hwnd, dc) == 0) + xpanic("error releasing Popover window DC for reshaping", GetLastError()); + } + break; // defer to DefWindowProc() + case WM_NCCALCSIZE: + { + RECT *r = (RECT *) lParam; + NCCALCSIZE_PARAMS *np = (NCCALCSIZE_PARAMS *) lParam; + popoverRect pr; + + if (wParam != FALSE) + r = &np->rgrc[0]; + pr.left = (intptr_t) (r->left); + pr.top = (intptr_t) (r->top); + pr.right = (intptr_t) (r->right); + pr.bottom = (intptr_t) (r->bottom); + popoverWindowSizeToClientSize(p, &pr); + r->left = (LONG) (pr.left); + r->top = (LONG) (pr.top); + r->right = (LONG) (pr.right); + r->bottom = (LONG) (pr.bottom); + return 0; + } + case WM_PAINT: + dc = BeginPaint(hwnd, &ps); + GetClientRect(hwnd, &r); + FillRect(dc, &r, GetSysColorBrush(COLOR_ACTIVECAPTION)); + FrameRect(dc, &r, GetStockPen(WHITE_BRUSH)); + EndPaint(hwnd, &ps); + return 0; + case msgPopoverPrepareLeftRight: + case msgPopoverPrepareTopBottom: + // TODO window edge detection + { + RECT r; + LONG width = 200, height = 200; + popoverRect control; + uintptr_t side; + popoverRect out; + + if (GetWindowRect((HWND) wParam, &r) == 0) + xpanic("error getting window rect of Popover target", GetLastError()); + control.left = (intptr_t) (r.left); + control.top = (intptr_t) (r.top); + control.right = (intptr_t) (r.right); + control.bottom = (intptr_t) (r.bottom); + switch (uMsg) { + case msgPopoverPrepareLeftRight: + side = popoverPointLeft; + break; + case msgPopoverPrepareTopBottom: + side = popoverPointTop; + break; + } + out = popoverPointAt(p, control, (intptr_t) width, (intptr_t) height, side); + if (MoveWindow(hwnd, out.left, out.top, out.right - out.left, out.bottom - out.top, TRUE) == 0) + xpanic("error repositioning Popover", GetLastError()); + } + return 0; + } + return DefWindowProcW(hwnd, uMsg, wParam, lParam); +} + +HWND button; + +LRESULT CALLBACK wndproc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + switch (uMsg) { + case WM_COMMAND: + if (HIWORD(wParam) == BN_CLICKED && LOWORD(wParam) == 100) { + SendMessageW(popoverWindow, msgPopoverPrepareLeftRight, (WPARAM) button, 0); + ShowWindow(popoverWindow, SW_SHOW); + UpdateWindow(popoverWindow); + return 0; + } + break; + case WM_CLOSE: + PostQuitMessage(0); + return 0; + } + return DefWindowProcW(hwnd, uMsg, wParam, lParam); +} + +int main(int argc, char *argv[]) +{ + WNDCLASSW wc; + HWND mainwin; + MSG msg; + + p = popoverDataNew(NULL); + // TODO null check + + ZeroMemory(&wc, sizeof (WNDCLASSW)); + wc.lpszClassName = L"popover"; + wc.lpfnWndProc = popoverproc; + wc.hbrBackground = (HBRUSH) (COLOR_BTNFACE + 1); + wc.style = CS_DROPSHADOW | CS_NOCLOSE; + if (RegisterClassW(&wc) == 0) + abort(); + popoverWindow = CreateWindowExW(WS_EX_TOPMOST, + L"popover", L"", + WS_POPUP, + 0, 0, 150, 100, + NULL, NULL, NULL, NULL); + if (popoverWindow == NULL) + abort(); + + ZeroMemory(&wc, sizeof (WNDCLASSW)); + wc.lpszClassName = L"mainwin"; + wc.lpfnWndProc = wndproc; + wc.hbrBackground = (HBRUSH) (COLOR_BTNFACE + 1); + if (RegisterClassW(&wc) == 0) + abort(); + mainwin = CreateWindowExW(0, + L"mainwin", L"Main Window", + WS_OVERLAPPEDWINDOW, + 0, 0, 150, 100, + NULL, NULL, NULL, NULL); + if (mainwin == NULL) + abort(); + button = CreateWindowExW(0, + L"button", L"Click Me", + BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE, + 20, 20, 100, 40, + mainwin, (HMENU) 100, NULL, NULL); + if (button == NULL) + abort(); + ShowWindow(mainwin, SW_SHOWDEFAULT); + if (UpdateWindow(mainwin) == 0) + abort(); + while (GetMessageW(&msg, NULL, 0, 0) > 0) { + TranslateMessage(&msg); + DispatchMessageW(&msg); + } + return 0; +} diff --git a/popover/popover.c b/popover/popover.c new file mode 100644 index 0000000..2c2bf66 --- /dev/null +++ b/popover/popover.c @@ -0,0 +1,174 @@ +// 9 october 2014 +#include +#include +#include "popover.h" + +#define ARROWHEIGHT 8 +#define ARROWWIDTH 8 /* should be the same for smooth lines on Windows (TODO is there a better/nicer looking way?) */ + +struct popover { + void *gopopover; + + // a nice consequence of this design is that it allows four arrowheads to jut out at once; in practice only one will ever be used, but hey — simple implementation! + intptr_t arrowLeft; + intptr_t arrowTop; + intptr_t arrowRight; + intptr_t arrowBottom; +}; + +popover *popoverDataNew(void *gopopover) +{ + popover *p; + + p = (popover *) malloc(sizeof (popover)); + if (p != NULL) { + p->gopopover = gopopover; + p->arrowLeft = -1; + p->arrowTop = 20;//TODO-1; + p->arrowRight = -1; + p->arrowBottom = -1; + } + return p; +} + +int popoverMakeFramePoints(popover *p, intptr_t width, intptr_t height, popoverPoint pt[20]) +{ + int n; + intptr_t xmax, ymax; + + n = 0; + + // figure out the xmax and ymax of the box + xmax = width; + if (p->arrowRight >= 0) + xmax -= ARROWWIDTH; + ymax = height; + if (p->arrowBottom >= 0) + ymax -= ARROWHEIGHT; + + // the first point is either at (0,0), (0,arrowHeight), (arrowWidth,0), or (arrowWidth,arrowHeight) + pt[n].x = 0; + if (p->arrowLeft >= 0) + pt[n].x = ARROWWIDTH; + pt[n].y = 0; + if (p->arrowTop >= 0) + pt[n].y = ARROWHEIGHT; + n++; + + // the left side + pt[n].x = pt[n - 1].x; + if (p->arrowLeft >= 0) { + pt[n].y = pt[n - 1].y + p->arrowLeft; + n++; + pt[n].x = pt[n - 1].x - ARROWWIDTH; + pt[n].y = pt[n - 1].y + ARROWHEIGHT; + n++; + pt[n].x = pt[n - 1].x + ARROWWIDTH; + pt[n].y = pt[n - 1].y + ARROWHEIGHT; + n++; + pt[n].x = pt[n - 1].x; + } + pt[n].y = ymax; + n++; + + // the bottom side + pt[n].y = pt[n - 1].y; + if (p->arrowBottom >= 0) { + pt[n].x = pt[n - 1].x + p->arrowBottom; + n++; + pt[n].x = pt[n - 1].x + ARROWWIDTH; + pt[n].y = pt[n - 1].y + ARROWHEIGHT; + n++; + pt[n].x = pt[n - 1].x + ARROWWIDTH; + pt[n].y = pt[n - 1].y - ARROWHEIGHT; + n++; + pt[n].y = pt[n - 1].y; + } + pt[n].x = xmax; + n++; + + // the right side + pt[n].x = pt[n - 1].x; + if (p->arrowRight >= 0) { + pt[n].y = pt[0].y + p->arrowRight + (ARROWHEIGHT * 2); + n++; + pt[n].x = pt[n - 1].x + ARROWWIDTH; + pt[n].y = pt[n - 1].y - ARROWHEIGHT; + n++; + pt[n].x = pt[n - 1].x - ARROWWIDTH; + pt[n].y = pt[n - 1].y - ARROWHEIGHT; + n++; + pt[n].x = pt[n - 1].x; + } + pt[n].y = pt[0].y; + n++; + + // the top side + pt[n].y = pt[n - 1].y; + if (p->arrowTop >= 0) { + pt[n].x = pt[0].x + p->arrowTop + (ARROWWIDTH * 2); + n++; + pt[n].x = pt[n - 1].x - ARROWWIDTH; + pt[n].y = pt[n - 1].y - ARROWHEIGHT; + n++; + pt[n].x = pt[n - 1].x - ARROWWIDTH; + pt[n].y = pt[n - 1].y + ARROWHEIGHT; + n++; + pt[n].y = pt[n - 1].y; + } + pt[n].x = pt[0].x; + n++; + + return n; +} + +void popoverWindowSizeToClientSize(popover *p, popoverRect *r) +{ + r->left++; + r->top++; + r->right--; + r->bottom--; + if (p->arrowLeft >= 0) + r->left += ARROWWIDTH; + if (p->arrowRight >= 0) + r->right -= ARROWWIDTH; + if (p->arrowTop >= 0) + r->top += ARROWHEIGHT; + if (p->arrowBottom >= 0) + r->bottom -= ARROWHEIGHT; +} + +// TODO window edge detection +popoverRect popoverPointAt(popover *p, popoverRect control, intptr_t width, intptr_t height, unsigned int side) +{ + intptr_t x, y; + popoverRect out; + + // account for border + width += 2; + height += 2; + p->arrowLeft = -1; + p->arrowRight = -1; + p->arrowTop = -1; + p->arrowBottom = -1; + // TODO right and bottom + switch (side) { + case popoverPointLeft: + width += ARROWWIDTH; + p->arrowLeft = height / 2 - ARROWHEIGHT; + x = control.right; + y = control.top - ((height - (control.bottom - control.top)) / 2); + break; + case popoverPointTop: + height += ARROWHEIGHT; + p->arrowTop = width / 2 - ARROWWIDTH; + x = control.left - ((width - (control.right - control.left)) / 2); + y = control.bottom; + break; + } + out.left = x; + out.top = y; + out.right = x + width; + out.bottom = y + height; + return out; +} diff --git a/popover/popover.h b/popover/popover.h new file mode 100644 index 0000000..28220e4 --- /dev/null +++ b/popover/popover.h @@ -0,0 +1,30 @@ +// 11 october 2014 + +typedef struct popover popover; +typedef struct popoverPoint popoverPoint; +typedef struct popoverRect popoverRect; + +struct popoverPoint { + intptr_t x; + intptr_t y; +}; + +struct popoverRect { + intptr_t left; + intptr_t top; + intptr_t right; + intptr_t bottom; +}; + +// note the order: flipping sides is as easy as side ^ 1 +enum { + popoverPointLeft, + popoverPointRight, + popoverPointTop, + popoverPointBottom, +}; + +popover *popoverDataNew(void *); +int popoverMakeFramePoints(popover *, intptr_t, intptr_t, popoverPoint[20]); +void popoverWindowSizeToClientSize(popover *, popoverRect *); +popoverRect popoverPointAt(popover *, popoverRect, intptr_t, intptr_t, unsigned int); diff --git a/windowspopover/main.c b/windowspopover/main.c deleted file mode 100644 index 0bf368f..0000000 --- a/windowspopover/main.c +++ /dev/null @@ -1,245 +0,0 @@ -// 9 october 2014 -#define UNICODE -#define _UNICODE -#define STRICT -#define STRICT_TYPED_ITEMIDS -// get Windows version right; right now Windows XP -#define WINVER 0x0501 -#define _WIN32_WINNT 0x0501 -#define _WIN32_WINDOWS 0x0501 /* according to Microsoft's winperf.h */ -#define _WIN32_IE 0x0600 /* according to Microsoft's sdkddkver.h */ -#define NTDDI_VERSION 0x05010000 /* according to Microsoft's sdkddkver.h */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "popover.h" - -// #qo LIBS: user32 kernel32 gdi32 - -// TODO -// - should the parent window appear deactivated? - -HWND popoverWindow; - -void xpanic(char *msg, DWORD err) -{ - printf("%d | %s\n", err, msg); - abort(); -} - -popover *p; - -HRGN makePopoverRegion(HDC dc, LONG width, LONG height) -{ - popoverPoint ppt[20]; - POINT pt[20]; - int i, n; - HRGN region; - - n = popoverMakeFramePoints(p, (intptr_t) width, (intptr_t) height, ppt); - for (i = 0; i < n; i++) { - pt[i].x = (LONG) (ppt[i].x); - pt[i].y = (LONG) (ppt[i].y); - } - - if (BeginPath(dc) == 0) - xpanic("error beginning path for Popover shape", GetLastError()); - if (Polyline(dc, pt, n) == 0) - xpanic("error drawing lines in Popover shape", GetLastError()); - if (EndPath(dc) == 0) - xpanic("error ending path for Popover shape", GetLastError()); - region = PathToRegion(dc); - if (region == NULL) - xpanic("error converting Popover shape path to region", GetLastError()); - return region; -} - -#define msgPopoverPrepareLeftRight (WM_APP+50) -#define msgPopoverPrepareTopBottom (WM_APP+51) - -LRESULT CALLBACK popoverproc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - PAINTSTRUCT ps; - HDC dc; - HRGN region; - RECT r; - LONG width; - LONG height; - WINDOWPOS *wp; - HBRUSH brush; - - switch (uMsg) { - case WM_NCPAINT: - if (GetWindowRect(hwnd, &r) == 0) - xpanic("error getting Popover window rect for shape redraw", GetLastError()); - width = r.right - r.left; - height = r.bottom - r.top; - dc = GetWindowDC(hwnd); - if (dc == NULL) - xpanic("error getting Popover window DC for drawing border", GetLastError()); - region = makePopoverRegion(dc, width, height); - // don't call FillRgn(); WM_ERASEBKGND seems to do this to the non-client area for us already :S (TODO confirm) - // TODO arrow is black in wine - brush = (HBRUSH) GetStockObject(BLACK_BRUSH); - if (brush == NULL) - xpanic("error getting Popover border brush", GetLastError()); - if (FrameRgn(dc, region, brush, 1, 1) == 0) - xpanic("error drawing Popover border", GetLastError()); - if (DeleteObject(region) == 0) - xpanic("error deleting Popover shape region", GetLastError()); - if (ReleaseDC(hwnd, dc) == 0) - xpanic("error releasing Popover window DC for shape drawing", GetLastError()); - return 0; - case WM_WINDOWPOSCHANGED: - // this must be here; if it's in WM_NCPAINT weird things happen (see http://stackoverflow.com/questions/26288303/why-is-my-client-rectangle-drawing-behaving-bizarrely-pictures-provided-if-i-t) - wp = (WINDOWPOS *) lParam; - if ((wp->flags & SWP_NOSIZE) == 0) { - dc = GetWindowDC(hwnd); - if (dc == NULL) - xpanic("error getting Popover window DC for reshaping", GetLastError()); - region = makePopoverRegion(dc, wp->cx, wp->cy); - if (SetWindowRgn(hwnd, region, TRUE) == 0) - xpanic("error setting Popover shape", GetLastError()); - // don't delete the region; the window manager owns it now - if (ReleaseDC(hwnd, dc) == 0) - xpanic("error releasing Popover window DC for reshaping", GetLastError()); - } - break; // defer to DefWindowProc() - case WM_NCCALCSIZE: - { - RECT *r = (RECT *) lParam; - NCCALCSIZE_PARAMS *np = (NCCALCSIZE_PARAMS *) lParam; - popoverRect pr; - - if (wParam != FALSE) - r = &np->rgrc[0]; - pr.left = (intptr_t) (r->left); - pr.top = (intptr_t) (r->top); - pr.right = (intptr_t) (r->right); - pr.bottom = (intptr_t) (r->bottom); - popoverWindowSizeToClientSize(p, &pr); - r->left = (LONG) (pr.left); - r->top = (LONG) (pr.top); - r->right = (LONG) (pr.right); - r->bottom = (LONG) (pr.bottom); - return 0; - } - case WM_PAINT: - dc = BeginPaint(hwnd, &ps); - GetClientRect(hwnd, &r); - FillRect(dc, &r, GetSysColorBrush(COLOR_ACTIVECAPTION)); - FrameRect(dc, &r, GetStockPen(WHITE_BRUSH)); - EndPaint(hwnd, &ps); - return 0; - case msgPopoverPrepareLeftRight: - case msgPopoverPrepareTopBottom: - // TODO window edge detection - { - RECT r; - LONG width = 200, height = 200; - popoverRect control; - uintptr_t side; - popoverRect out; - - if (GetWindowRect((HWND) wParam, &r) == 0) - xpanic("error getting window rect of Popover target", GetLastError()); - control.left = (intptr_t) (r.left); - control.top = (intptr_t) (r.top); - control.right = (intptr_t) (r.right); - control.bottom = (intptr_t) (r.bottom); - switch (uMsg) { - case msgPopoverPrepareLeftRight: - side = popoverPointLeft; - break; - case msgPopoverPrepareTopBottom: - side = popoverPointTop; - break; - } - out = popoverPointAt(p, control, (intptr_t) width, (intptr_t) height, side); - if (MoveWindow(hwnd, out.left, out.top, out.right - out.left, out.bottom - out.top, TRUE) == 0) - xpanic("error repositioning Popover", GetLastError()); - } - return 0; - } - return DefWindowProcW(hwnd, uMsg, wParam, lParam); -} - -HWND button; - -LRESULT CALLBACK wndproc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - switch (uMsg) { - case WM_COMMAND: - if (HIWORD(wParam) == BN_CLICKED && LOWORD(wParam) == 100) { - SendMessageW(popoverWindow, msgPopoverPrepareLeftRight, (WPARAM) button, 0); - ShowWindow(popoverWindow, SW_SHOW); - UpdateWindow(popoverWindow); - return 0; - } - break; - case WM_CLOSE: - PostQuitMessage(0); - return 0; - } - return DefWindowProcW(hwnd, uMsg, wParam, lParam); -} - -int main(int argc, char *argv[]) -{ - WNDCLASSW wc; - HWND mainwin; - MSG msg; - - p = popoverDataNew(NULL); - // TODO null check - - ZeroMemory(&wc, sizeof (WNDCLASSW)); - wc.lpszClassName = L"popover"; - wc.lpfnWndProc = popoverproc; - wc.hbrBackground = (HBRUSH) (COLOR_BTNFACE + 1); - wc.style = CS_DROPSHADOW | CS_NOCLOSE; - if (RegisterClassW(&wc) == 0) - abort(); - popoverWindow = CreateWindowExW(WS_EX_TOPMOST, - L"popover", L"", - WS_POPUP, - 0, 0, 150, 100, - NULL, NULL, NULL, NULL); - if (popoverWindow == NULL) - abort(); - - ZeroMemory(&wc, sizeof (WNDCLASSW)); - wc.lpszClassName = L"mainwin"; - wc.lpfnWndProc = wndproc; - wc.hbrBackground = (HBRUSH) (COLOR_BTNFACE + 1); - if (RegisterClassW(&wc) == 0) - abort(); - mainwin = CreateWindowExW(0, - L"mainwin", L"Main Window", - WS_OVERLAPPEDWINDOW, - 0, 0, 150, 100, - NULL, NULL, NULL, NULL); - if (mainwin == NULL) - abort(); - button = CreateWindowExW(0, - L"button", L"Click Me", - BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE, - 20, 20, 100, 40, - mainwin, (HMENU) 100, NULL, NULL); - if (button == NULL) - abort(); - ShowWindow(mainwin, SW_SHOWDEFAULT); - if (UpdateWindow(mainwin) == 0) - abort(); - while (GetMessageW(&msg, NULL, 0, 0) > 0) { - TranslateMessage(&msg); - DispatchMessageW(&msg); - } - return 0; -} diff --git a/windowspopover/popover.c b/windowspopover/popover.c deleted file mode 100644 index 2c2bf66..0000000 --- a/windowspopover/popover.c +++ /dev/null @@ -1,174 +0,0 @@ -// 9 october 2014 -#include -#include -#include "popover.h" - -#define ARROWHEIGHT 8 -#define ARROWWIDTH 8 /* should be the same for smooth lines on Windows (TODO is there a better/nicer looking way?) */ - -struct popover { - void *gopopover; - - // a nice consequence of this design is that it allows four arrowheads to jut out at once; in practice only one will ever be used, but hey — simple implementation! - intptr_t arrowLeft; - intptr_t arrowTop; - intptr_t arrowRight; - intptr_t arrowBottom; -}; - -popover *popoverDataNew(void *gopopover) -{ - popover *p; - - p = (popover *) malloc(sizeof (popover)); - if (p != NULL) { - p->gopopover = gopopover; - p->arrowLeft = -1; - p->arrowTop = 20;//TODO-1; - p->arrowRight = -1; - p->arrowBottom = -1; - } - return p; -} - -int popoverMakeFramePoints(popover *p, intptr_t width, intptr_t height, popoverPoint pt[20]) -{ - int n; - intptr_t xmax, ymax; - - n = 0; - - // figure out the xmax and ymax of the box - xmax = width; - if (p->arrowRight >= 0) - xmax -= ARROWWIDTH; - ymax = height; - if (p->arrowBottom >= 0) - ymax -= ARROWHEIGHT; - - // the first point is either at (0,0), (0,arrowHeight), (arrowWidth,0), or (arrowWidth,arrowHeight) - pt[n].x = 0; - if (p->arrowLeft >= 0) - pt[n].x = ARROWWIDTH; - pt[n].y = 0; - if (p->arrowTop >= 0) - pt[n].y = ARROWHEIGHT; - n++; - - // the left side - pt[n].x = pt[n - 1].x; - if (p->arrowLeft >= 0) { - pt[n].y = pt[n - 1].y + p->arrowLeft; - n++; - pt[n].x = pt[n - 1].x - ARROWWIDTH; - pt[n].y = pt[n - 1].y + ARROWHEIGHT; - n++; - pt[n].x = pt[n - 1].x + ARROWWIDTH; - pt[n].y = pt[n - 1].y + ARROWHEIGHT; - n++; - pt[n].x = pt[n - 1].x; - } - pt[n].y = ymax; - n++; - - // the bottom side - pt[n].y = pt[n - 1].y; - if (p->arrowBottom >= 0) { - pt[n].x = pt[n - 1].x + p->arrowBottom; - n++; - pt[n].x = pt[n - 1].x + ARROWWIDTH; - pt[n].y = pt[n - 1].y + ARROWHEIGHT; - n++; - pt[n].x = pt[n - 1].x + ARROWWIDTH; - pt[n].y = pt[n - 1].y - ARROWHEIGHT; - n++; - pt[n].y = pt[n - 1].y; - } - pt[n].x = xmax; - n++; - - // the right side - pt[n].x = pt[n - 1].x; - if (p->arrowRight >= 0) { - pt[n].y = pt[0].y + p->arrowRight + (ARROWHEIGHT * 2); - n++; - pt[n].x = pt[n - 1].x + ARROWWIDTH; - pt[n].y = pt[n - 1].y - ARROWHEIGHT; - n++; - pt[n].x = pt[n - 1].x - ARROWWIDTH; - pt[n].y = pt[n - 1].y - ARROWHEIGHT; - n++; - pt[n].x = pt[n - 1].x; - } - pt[n].y = pt[0].y; - n++; - - // the top side - pt[n].y = pt[n - 1].y; - if (p->arrowTop >= 0) { - pt[n].x = pt[0].x + p->arrowTop + (ARROWWIDTH * 2); - n++; - pt[n].x = pt[n - 1].x - ARROWWIDTH; - pt[n].y = pt[n - 1].y - ARROWHEIGHT; - n++; - pt[n].x = pt[n - 1].x - ARROWWIDTH; - pt[n].y = pt[n - 1].y + ARROWHEIGHT; - n++; - pt[n].y = pt[n - 1].y; - } - pt[n].x = pt[0].x; - n++; - - return n; -} - -void popoverWindowSizeToClientSize(popover *p, popoverRect *r) -{ - r->left++; - r->top++; - r->right--; - r->bottom--; - if (p->arrowLeft >= 0) - r->left += ARROWWIDTH; - if (p->arrowRight >= 0) - r->right -= ARROWWIDTH; - if (p->arrowTop >= 0) - r->top += ARROWHEIGHT; - if (p->arrowBottom >= 0) - r->bottom -= ARROWHEIGHT; -} - -// TODO window edge detection -popoverRect popoverPointAt(popover *p, popoverRect control, intptr_t width, intptr_t height, unsigned int side) -{ - intptr_t x, y; - popoverRect out; - - // account for border - width += 2; - height += 2; - p->arrowLeft = -1; - p->arrowRight = -1; - p->arrowTop = -1; - p->arrowBottom = -1; - // TODO right and bottom - switch (side) { - case popoverPointLeft: - width += ARROWWIDTH; - p->arrowLeft = height / 2 - ARROWHEIGHT; - x = control.right; - y = control.top - ((height - (control.bottom - control.top)) / 2); - break; - case popoverPointTop: - height += ARROWHEIGHT; - p->arrowTop = width / 2 - ARROWWIDTH; - x = control.left - ((width - (control.right - control.left)) / 2); - y = control.bottom; - break; - } - out.left = x; - out.top = y; - out.right = x + width; - out.bottom = y + height; - return out; -} diff --git a/windowspopover/popover.h b/windowspopover/popover.h deleted file mode 100644 index 28220e4..0000000 --- a/windowspopover/popover.h +++ /dev/null @@ -1,30 +0,0 @@ -// 11 october 2014 - -typedef struct popover popover; -typedef struct popoverPoint popoverPoint; -typedef struct popoverRect popoverRect; - -struct popoverPoint { - intptr_t x; - intptr_t y; -}; - -struct popoverRect { - intptr_t left; - intptr_t top; - intptr_t right; - intptr_t bottom; -}; - -// note the order: flipping sides is as easy as side ^ 1 -enum { - popoverPointLeft, - popoverPointRight, - popoverPointTop, - popoverPointBottom, -}; - -popover *popoverDataNew(void *); -int popoverMakeFramePoints(popover *, intptr_t, intptr_t, popoverPoint[20]); -void popoverWindowSizeToClientSize(popover *, popoverRect *); -popoverRect popoverPointAt(popover *, popoverRect, intptr_t, intptr_t, unsigned int); -- cgit v1.2.3