libui/windows/util.c

135 lines
3.9 KiB
C

// 6 april 2015
#include "uipriv_windows.h"
// TODO move to text.c
intmax_t uiWindowsWindowTextWidth(HWND hwnd)
{
LRESULT len;
WCHAR *text;
HDC dc;
HFONT prevfont;
SIZE size;
size.cx = 0;
size.cy = 0;
// first we need the window text
len = SendMessageW(hwnd, WM_GETTEXTLENGTH, 0, 0);
if (len == 0) // no text; nothing to do
return 0;
text = (WCHAR *) uiAlloc((len + 1) * sizeof (WCHAR), "WCHAR[]");
// note the comparison: the size includes the null terminator, but the return does not
if (GetWindowText(hwnd, text, len + 1) != len)
logLastError("error getting window text in uiWindowsWindowTextWidth()");
// now we can do the calculations
dc = GetDC(hwnd);
if (dc == NULL)
logLastError("error getting DC in uiWindowsWindowTextWidth()");
prevfont = (HFONT) SelectObject(dc, hMessageFont);
if (prevfont == NULL)
logLastError("error loading control font into device context in uiWindowsWindowTextWidth()");
if (GetTextExtentPoint32W(dc, text, len, &size) == 0)
logLastError("error getting text extent point in uiWindowsWindowTextWidth()");
if (SelectObject(dc, prevfont) != hMessageFont)
logLastError("error restoring previous font into device context in uiWindowsWindowTextWidth()");
if (ReleaseDC(hwnd, dc) == 0)
logLastError("error releasing DC in uiWindowsWindowTextWidth()");
uiFree(text);
return size.cx;
}
// this is a helper function that takes the logic of determining window classes and puts it all in one place
// there are a number of places where we need to know what window class an arbitrary handle has
// theoretically we could use the class atom to avoid a _wcsicmp()
// however, raymond chen advises against this - http://blogs.msdn.com/b/oldnewthing/archive/2004/10/11/240744.aspx (and we're not in control of the Tab class, before you say anything)
// usage: windowClassOf(hwnd, L"class 1", L"class 2", ..., NULL)
int windowClassOf(HWND hwnd, ...)
{
// MSDN says 256 is the maximum length of a class name; add a few characters just to be safe (because it doesn't say whether this includes the terminating null character)
#define maxClassName 260
WCHAR classname[maxClassName + 1];
va_list ap;
WCHAR *curname;
int i;
if (GetClassNameW(hwnd, classname, maxClassName) == 0)
logLastError("error getting name of window class in windowClassOf()");
va_start(ap, hwnd);
i = 0;
for (;;) {
curname = va_arg(ap, WCHAR *);
if (curname == NULL)
break;
if (_wcsicmp(classname, curname) == 0) {
va_end(ap);
return i;
}
i++;
}
// no match
va_end(ap);
return -1;
}
void complain(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
fprintf(stderr, "[libui] ");
vfprintf(stderr, fmt, ap);
fprintf(stderr, "\n");
va_end(ap);
abort();
}
// wrapper around MapWindowRect() that handles the complex error handling
void mapWindowRect(HWND from, HWND to, RECT *r)
{
DWORD le;
SetLastError(0);
if (MapWindowRect(from, to, r) == 0) {
le = GetLastError();
SetLastError(le); // just to be safe
if (le != 0)
logLastError("error calling MapWindowRect() in mapWindowRect()");
}
}
DWORD getStyle(HWND hwnd)
{
return (DWORD) GetWindowLongPtrW(hwnd, GWL_STYLE);
}
void setStyle(HWND hwnd, DWORD style)
{
SetWindowLongPtrW(hwnd, GWL_STYLE, (LONG_PTR) style);
}
DWORD getExStyle(HWND hwnd)
{
return (DWORD) GetWindowLongPtrW(hwnd, GWL_EXSTYLE);
}
void setExStyle(HWND hwnd, DWORD exstyle)
{
SetWindowLongPtrW(hwnd, GWL_EXSTYLE, (LONG_PTR) exstyle);
}
#define swpflags (SWP_NOACTIVATE | SWP_NOOWNERZORDER)
void moveWindow(HWND hwnd, intmax_t x, intmax_t y, intmax_t width, intmax_t height)
{
if (SetWindowPos(hwnd, NULL, x, y, width, height, swpflags | SWP_NOZORDER) == 0)
logLastError("error moving window in moveWindow()");
}
void moveAndReorderWindow(HWND hwnd, HWND insertAfter, intmax_t x, intmax_t y, intmax_t width, intmax_t height)
{
if (SetWindowPos(hwnd, insertAfter, x, y, width, height, swpflags) == 0)
logLastError("error moving and reordering window in moveAndReorderWindow()");
}