c - What is the proper use of DTM_GETIDEALSIZE? Treating the returned size as pixels gives me very large, sometimes variable, heights -
i'm trying autosize date-time picker controls dtm_getidealsize, don't quite how use message properly. while widths returned seem fine if treated pixels, heights seem not way off, change on time!
the sample program below creates 3 date-time pickers. first shows both date , time custom format, second shows dates dts_shortdatecenturyformat, , third shows times dts_timeformat. resizing window resizes 3 pickers using dtm_getidealsize. widths seem fine. however, heights of first 2 100, , height of last (the time picker) seems start @ 98 or , decreases 2 each resize until reaches 16, @ point stays @ 16.
this tested both windows vista , windows 7. error checking in below program inconsistent (but errors not checked purposes of keeping simple test example). however, note msdn explicitly documents dtm_getidealsize ever returning true no error condition specified.
thanks.
// 3 june 2015 #define unicode #define _unicode #define strict #define strict_typed_itemids #define cinterface #define winver 0x0600 #define _win32_winnt 0x0600 #define _win32_windows 0x0600 #define _win32_ie 0x0700 #define ntddi_version 0x06000000 #include <windows.h> #include <commctrl.h> #include <stdint.h> #include <uxtheme.h> #include <string.h> #include <wchar.h> #include <windowsx.h> #include <vsstyle.h> #include <vssym32.h> #include <stdarg.h> #include <oleacc.h> #include <stdio.h> void die(char *s) { // todo } hwnd mainwin; hwnd dtp1, dtp2, dtp3; void idealsize(hwnd dtp, char *n, int *x, int *y) { size s; s.cx = 0; s.cy = 0; printf("%s | %i32d ", n, sendmessagew(dtp, dtm_getidealsize, 0, (lparam) (&s))); printf("%i32d %i32d\n", s.cx, s.cy); movewindow(dtp, *x, *y, s.cx, s.cy, true); *y += s.cy; } lresult callback wndproc(hwnd hwnd, uint umsg, wparam wparam, lparam lparam) { int x, y; size s; switch (umsg) { case wm_close: postquitmessage(0); return 0; case wm_size: x = 10; y = 10; idealsize(dtp1, "1", &x, &y); idealsize(dtp2, "2", &x, &y); idealsize(dtp3, "3", &x, &y); break; } return defwindowprocw(hwnd, umsg, wparam, lparam); } static hwnd makedtp(dword style, wchar *format) { hwnd hwnd; hwnd = createwindowexw(ws_ex_clientedge, datetimepick_classw, l"", style | ws_tabstop | ws_child | ws_visible, 0, 0, 100, 100, mainwin, null, getmodulehandle(null), null); if (format != null) if (sendmessagew(hwnd, dtm_setformat, 0, (lparam) format) == 0) die("error applying format string date/time picker in finishnewdatetimepicker()"); return hwnd; } #define gli(what, buf, n) getlocaleinfoex(locale_name_user_default, what, buf, n) hwnd makedatetimepicker(void) { wchar *date, *time, *datetime; int ndate, ntime; int n; hwnd hwnd; // todo verify returns century year ndate = gli(locale_sshortdate, null, 0); if (ndate == 0) die("error getting date string length in uinewdatetimepicker()"); date = (wchar *) malloc(ndate * sizeof (wchar)); if (gli(locale_sshortdate, date, ndate) == 0) die("error geting date string in uinewdatetimepicker()"); ntime = gli(locale_stimeformat, null, 0); if (ndate == 0) die("error getting time string length in uinewdatetimepicker()"); time = (wchar *) malloc(ntime * sizeof (wchar)); if (gli(locale_stimeformat, time, ntime) == 0) die("error geting time string in uinewdatetimepicker()"); n = _scwprintf(l"%s %s", date, time); datetime = (wchar *) malloc((n + 1) * sizeof (wchar)); snwprintf(datetime, n + 1, l"%s %s", date, time); hwnd = makedtp(0, datetime); free(datetime); free(time); free(date); return hwnd; } hwnd makedatepicker(void) { return makedtp(dts_shortdatecenturyformat, null); } hwnd maketimepicker(void) { return makedtp(dts_timeformat, null); } static void makewindows(void) { mainwin = createwindowexw(0, l"mainwin", l"full window", ws_overlappedwindow, cw_usedefault, cw_usedefault, 500, 500, null, null, getmodulehandle(null), null); dtp1 = makedatetimepicker(); dtp2 = makedatepicker(); dtp3 = maketimepicker(); } void initcommoncontrols(bool); int main(int argc, char *argv[]) { wndclassw wc; msg msg; hbrush b; initcommoncontrols(true); zeromemory(&wc, sizeof (wndclassw)); wc.lpszclassname = l"mainwin"; wc.lpfnwndproc = wndproc; wc.hinstance = getmodulehandle(null); wc.hicon = loadiconw(null, idi_application); wc.hcursor = loadcursorw(null, idc_arrow); wc.hbrbackground = (hbrush) (color_btnface + 1); registerclassw(&wc); makewindows(); showwindow(mainwin, sw_showdefault); updatewindow(mainwin); while (getmessagew(&msg, null, 0, 0) > 0) { translatemessage(&msg); dispatchmessage(&msg); } return 0; } static const char manifest[] = "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\"?>\n<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestversion=\"1.0\">\n<assemblyidentity\n version=\"1.0.0.0\"\n processorarchitecture=\"*\"\n name=\"companyname.productname.yourapplication\"\n type=\"win32\"\n/>\n<description>your application description here.</description>\n<dependency>\n <dependentassembly>\n <assemblyidentity\n type=\"win32\"\n name=\"microsoft.windows.common-controls\"\n version=\"6.0.0.0\"\n processorarchitecture=\"*\"\n publickeytoken=\"6595b64144ccf1df\"\n language=\"*\"\n />\n </dependentassembly>\n</dependency>\n</assembly>\n"; static ulong_ptr comctlmanifestcookie; static hmodule comctl32; void initcommoncontrols(bool comctl6) { wchar temppath[max_path + 1]; wchar filename[max_path + 1]; handle file; dword nexpected, ngot; actctx actctx; handle ac; initcommoncontrolsex icc; farproc f; // listed winapi in both microsoft's , mingw's headers, not on msdn reason bool (*winapi ficc)(const lpinitcommoncontrolsex); if (comctl6) { if (gettemppathw(max_path + 1, temppath) == 0) die("getting temporary path writing manifest file"); if (gettempfilenamew(temppath, l"manifest", 0, filename) == 0) die("getting temporary filename writing manifest file"); file = createfilew(filename, generic_write, 0, // don't share while writing null, create_always, file_attribute_normal, null); if (file == null) die("creating manifest file"); nexpected = (sizeof manifest / sizeof manifest[0]) - 1; // - 1 omit terminating null character) if (writefile(file, manifest, nexpected, &ngot, null) == 0) die("writing manifest file"); if (ngot != nexpected) die("short write manifest file"); if (closehandle(file) == 0) die("closing manifest file (this error here because not doing prevent windows being able use manifest file in activation context)"); zeromemory(&actctx, sizeof (actctx)); actctx.cbsize = sizeof (actctx); actctx.dwflags = actctx_flag_set_process_default; actctx.lpsource = filename; ac = createactctx(&actctx); if (ac == invalid_handle_value) die("creating activation context synthesized manifest file"); if (activateactctx(ac, &comctlmanifestcookie) == false) die("activating activation context synthesized manifest file"); } zeromemory(&icc, sizeof (initcommoncontrolsex)); icc.dwsize = sizeof (initcommoncontrolsex); icc.dwicc = icc_standard_classes | icc_progress_class | icc_tab_classes | icc_listview_classes | icc_updown_class | icc_bar_classes | icc_date_classes; comctl32 = loadlibraryw(l"comctl32.dll"); if (comctl32 == null) die("loading comctl32.dll"); f = getprocaddress(comctl32, "initcommoncontrolsex"); if (f == null) die("loading initcommoncontrolsex()"); ficc = (bool (*winapi)(const lpinitcommoncontrolsex)) f; if ((*ficc)(&icc) == false) die("initializing common controls (comctl32.dll)"); }
Comments
Post a Comment