#define WIN32_LEAN_AND_MEAN #include #include #include #include #include #include #include #include #include "resource.h" #pragma comment(lib, "comctl32.lib") #pragma comment(lib, "dbghelp.lib") #define UXCTRL #ifdef UXCTRL static const PCWSTR g_rebar = L"UxReBar"; static const PCWSTR g_tooltip = L"UxToolTip"; static const PCWSTR g_statusBar = L"UxStatusBar"; static const PCWSTR g_listView = L"UxListView"; static const PCWSTR g_header = L"UxHeader"; static const PCWSTR g_tab = L"UxTab"; static const PCWSTR g_treeview = L"UxTreeView"; static const PCWSTR g_trackbar = L"UxTrackBar"; static const PCWSTR g_spin = L"UxSpin"; static const PCWSTR g_progress = L"UxProgress"; static const PCWSTR g_hotkey = L"UxHotKey"; static const PCWSTR g_animate = L"UxAnimate"; static const PCWSTR g_dateTime = L"UxDateTimePicker"; static const PCWSTR g_monthCal = L"UxMonthCal"; static const PCWSTR g_combo = L"UxComboBox"; static const PCWSTR g_ipAddr = L"UxIPAddress"; static const PCWSTR g_page = L"UxPageScroller"; static const PCWSTR g_nativeFont = L"UxNativeFont"; #else static const PCWSTR g_rebar = REBARCLASSNAME; static const PCWSTR g_tooltip = TOOLTIPS_CLASS; static const PCWSTR g_statusBar = STATUSCLASSNAME; static const PCWSTR g_listView = WC_LISTVIEW; static const PCWSTR g_header = WC_HEADER; static const PCWSTR g_tab = WC_TABCONTROL; static const PCWSTR g_treeview = WC_TREEVIEW; static const PCWSTR g_trackbar = TRACKBAR_CLASS; static const PCWSTR g_spin = UPDOWN_CLASS; static const PCWSTR g_progress = PROGRESS_CLASS; static const PCWSTR g_hotkey = HOTKEY_CLASS; static const PCWSTR g_animate = ANIMATE_CLASS; static const PCWSTR g_dateTime = DATETIMEPICK_CLASS; static const PCWSTR g_monthCal = MONTHCAL_CLASS; static const PCWSTR g_combo = WC_COMBOBOX; static const PCWSTR g_ipAddr = WC_IPADDRESS; static const PCWSTR g_page = WC_PAGESCROLLER; static const PCWSTR g_nativeFont = WC_NATIVEFONTCTL; #endif enum { REBAR_WND, TOOLTIP_WND, STATUSBAR_WND, LISTVIEW_WND, HEADER_WND, TAB_WND, TREEVIEW_WND, TRACKBAR_WND, SPIN_WND, PROGRESS_WND, HOTKEY_WND, ANIMATE_WND, DATETIME_WND, MONTHCAL_WND, COMBOBOX_WND, IPADDR_WND, PAGE_WND, NATIVEFONT_WND, END_WND }; HWND g_hControls[END_WND] = {NULL}; HMODULE g_hMod = NULL; const UINT_PTR g_progressAnimateTimer = 1; VOID CALLBACK StepProgress(HWND hwnd, UINT msg, UINT_PTR idEvent, DWORD dwTime) { SendMessage(g_hControls[PROGRESS_WND], PBM_STEPIT, 0, 0); } void CreateChildControls(HWND hwnd) { SHFILEINFO shFile = {0}; IImageList* pImageList = (IImageList*)SHGetFileInfo(L".exe", FILE_ATTRIBUTE_NORMAL, &shFile, sizeof(shFile), SHGFI_USEFILEATTRIBUTES | SHGFI_SYSICONINDEX | SHGFI_SMALLICON); if(!pImageList) { wprintf(L"SHGetFileInfo failed with error %#x\n", GetLastError()); } PCWSTR classNames[] = {g_rebar, g_tooltip, g_statusBar, g_listView, g_header, g_tab, g_treeview, g_trackbar, g_spin, g_progress, g_hotkey, g_animate, g_dateTime, g_monthCal, g_combo, g_ipAddr, g_page, g_nativeFont, NULL}; DWORD additionalStyles[END_WND] = { CCS_NORESIZE | RBS_TOOLTIPS, TTS_ALWAYSTIP | TTS_BALLOON, 0, LVS_REPORT | LVS_NOSORTHEADER, HDS_BUTTONS, TCS_FIXEDWIDTH | TCS_FORCEICONLEFT, TVS_DISABLEDRAGDROP | TVS_NOTOOLTIPS | TVS_LINESATROOT, 0, UDS_ALIGNRIGHT | UDS_WRAP, 0, 0, ACS_AUTOPLAY | ACS_CENTER, DTS_LONGDATEFORMAT, MCS_WEEKNUMBERS, CBS_DROPDOWNLIST | CBS_HASSTRINGS | CBS_NOINTEGRALHEIGHT, 0, PGS_HORZ, NFS_ALL }; HMODULE hMod = g_hMod; for(int i = REBAR_WND, ctrlIndex = 0; i < END_WND; ++i, ++ctrlIndex) { DWORD column = ctrlIndex / 6; DWORD row = ctrlIndex % 6; DWORD rowHeight = 70; DWORD colWidth = 210; DWORD xOffset = 5; // so it's not right on the left edge DWORD yOffset = 5; DWORD xCoord = ((xOffset * (column + 1)) + (column * colWidth)); DWORD yCoord = (row * rowHeight) + (yOffset * (row + 1)); DWORD style = WS_VISIBLE | WS_CHILD | WS_BORDER; HWND hThisChild = CreateWindowEx( 0, classNames[i], classNames[i], style | additionalStyles[i], xCoord, yCoord, colWidth, rowHeight, hwnd, (HMENU)i, hMod, NULL ); g_hControls[i] = hThisChild; if(!hThisChild) { wprintf(L"Couldn't create window of class %s, err = %lu\n", classNames[i], GetLastError()); } else { switch(i) { case ANIMATE_WND: { Animate_OpenEx(hThisChild, hMod, MAKEINTRESOURCE(IDR_MOVIE)); } break; case REBAR_WND: { SetWindowPos(hThisChild, NULL, 0, 0, colWidth, 20, SWP_NOMOVE | SWP_NOZORDER); REBARBANDINFO band = {REBARBANDINFOA_V6_SIZE, 0}; band.fMask = RBBIM_TEXT | RBBIM_HEADERSIZE | RBBIM_SIZE | RBBIM_STYLE; band.lpText = L"ReBar / Coolbar (with tooltip)"; band.cx = colWidth; band.cxHeader = colWidth / 2; band.fStyle = RBBS_GRIPPERALWAYS; SendMessage(hThisChild, RB_INSERTBAND, -1, (LPARAM)&band); } break; case TOOLTIP_WND: { HWND hRebar = g_hControls[REBAR_WND]; TOOLINFO ti = {TTTOOLINFOW_V2_SIZE, 0}; ti.lpszText = L"Tooltip, neat huh!"; GetClientRect(hRebar, &ti.rect); ti.uFlags = TTF_SUBCLASS | TTF_IDISHWND; ti.uId = (UINT_PTR)hRebar; ti.hwnd = hRebar; SendMessage(hThisChild, TTM_ADDTOOL, 0, (WPARAM)&ti); SendMessage(hRebar, RB_SETTOOLTIPS, (WPARAM)hThisChild, 0); } break; case LISTVIEW_WND: { ListView_SetImageList(hThisChild, pImageList, LVSIL_SMALL); LVBKIMAGE lvIm = {0}; lvIm.ulFlags = (((GetVersion() & 0xFF) == 5) ? LVBKIF_SOURCE_URL : LVBKIF_SOURCE_NONE);; lvIm.xOffsetPercent = lvIm.yOffsetPercent = 50; lvIm.pszImage = L"file:///C:\\winnt\\web\\wvlogo.gif"; ListView_SetBkImage(hThisChild, &lvIm); LVCOLUMN lvCol = {}; lvCol.mask = LVCF_TEXT | LVCF_FMT | LVCF_SUBITEM | LVCF_WIDTH; lvCol.pszText = L"ListView"; lvCol.fmt = LVCFMT_IMAGE; lvCol.iSubItem = 0; lvCol.cx = colWidth / 2; ListView_InsertColumn(hThisChild, 0, &lvCol); lvCol.pszText = L"Report"; lvCol.fmt = LVCFMT_LEFT; lvCol.iSubItem = 1; lvCol.cx = colWidth / 2; ListView_InsertColumn(hThisChild, 1, &lvCol); for(int i = 0; i < 3; ++i) { WCHAR buf[50] = {0}; _swprintf(buf, L"Item %d", i); LVITEM lvItem[2] = {{}}; lvItem[0].mask = LVIF_IMAGE; lvItem[1].mask = LVIF_TEXT; lvItem[0].iItem = lvItem[1].iItem = i; lvItem[0].iSubItem = 0; lvItem[1].iSubItem = 1; lvItem[0].iImage = i + 1; lvItem[1].pszText = buf; int itemIndex = ListView_InsertItem(hThisChild, &lvItem[0]); lvItem[1].iItem = itemIndex; ListView_SetItem(hThisChild, &lvItem[1]); } } break; case HEADER_WND: { Header_SetImageList(hThisChild, pImageList); PWSTR pText[] = {L"Header", L"Control"}; for(int i = 0; i < 2; ++i) { HDITEM hdItem = {0}; hdItem.mask = HDI_IMAGE | HDI_TEXT | HDI_FORMAT | HDI_WIDTH; hdItem.cxy = colWidth / 2; hdItem.iImage = 4 + i; hdItem.pszText = pText[i]; hdItem.fmt = HDF_IMAGE | HDF_LEFT; Header_InsertItem(hThisChild, i, &hdItem); } } break; case TAB_WND: { PWSTR pText[] = {L"Tab", L"Control"}; TabCtrl_SetImageList(hThisChild, pImageList); for(int i = 0; i < 2; ++i) { TCITEM tc = {}; tc.mask = TCIF_IMAGE | TCIF_TEXT; tc.iImage = 6 + i; tc.pszText = pText[i]; TabCtrl_InsertItem(hThisChild, i, &tc); } } break; case TREEVIEW_WND: { TreeView_SetImageList(hThisChild, pImageList, TVSIL_NORMAL); TVINSERTSTRUCT tvIns = {0}; TVITEM& item = tvIns.item; tvIns.hParent = TVI_ROOT; tvIns.hInsertAfter = TVI_ROOT; item.mask = TVIF_IMAGE | TVIF_TEXT; PWSTR pText[] = {L"TreeView", L"Control", L"Test"}; HTREEITEM hParent = NULL; for(int i = 0; i < 3; ++i) { item.pszText = pText[i]; item.iImage = 8 + i; item.cChildren = i == 0 ? 1 : 0; hParent = TreeView_InsertItem(hThisChild, &tvIns); tvIns.hParent = (i < 2) ? hParent : NULL; tvIns.hInsertAfter = TVI_SORT; } } break; case PROGRESS_WND: { SendMessage(hThisChild, PBM_SETRANGE32, 0, 100); SendMessage(hThisChild, PBM_SETSTEP, 5, 0); SetTimer(hwnd, g_progressAnimateTimer, 250, &StepProgress); } break; case COMBOBOX_WND: { PCWSTR pText[] = {L"ComboBox", L"Window", L"Test"}; for(int i = 0; i < 3; ++i) { SendMessage(hThisChild, CB_ADDSTRING, 0, (LPARAM)pText[i]); } } break; case PAGE_WND: { PCWSTR pButtonText[] = {L"Pager", L"Window", L"Test"}; DWORD buttonWidth = (colWidth / 3) + 30; HWND hToolbar = CreateWindowEx( TBSTYLE_EX_MIXEDBUTTONS, TOOLBARCLASSNAME, NULL, WS_CHILD | WS_VISIBLE | CCS_NORESIZE | TBSTYLE_LIST, 0, 0, colWidth + 90, rowHeight, hThisChild, (HMENU)0x4000, hMod, NULL ); TBBUTTON tb[3] = {0}; for(int i = 0; i < 3; ++i) { tb[i].idCommand = i + 1; tb[i].iBitmap = I_IMAGENONE; tb[i].fsState = TBSTATE_ENABLED; tb[i].fsStyle = BTNS_BUTTON | BTNS_SHOWTEXT; tb[i].iString = (INT_PTR)pButtonText[i]; } SendMessage(hToolbar, TB_BUTTONSTRUCTSIZE, sizeof(tb[0]), 0); SendMessage(hToolbar, TB_ADDBUTTONS, 3, (WPARAM)tb); SendMessage(hToolbar, TB_SETBUTTONSIZE, ((colWidth / 3) + 30), rowHeight); Pager_SetChild(hThisChild, hToolbar); } break; } } // this just runs along the bottom on the window, it doesn't need a slot // in the window if(i == STATUSBAR_WND) { --ctrlIndex; continue; } } } LRESULT WINAPI WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { LRESULT ret = 0; switch(msg) { case WM_CREATE: { CreateChildControls(hwnd); } break; case WM_CLOSE: { KillTimer(hwnd, g_progressAnimateTimer); DestroyWindow(hwnd); } break; case WM_DESTROY: { PostQuitMessage(0); } break; case WM_NOTIFY: { NMHDR* pHdr = (NMHDR*)lParam; switch(pHdr->code) { case PGN_CALCSIZE: { LPNMPGCALCSIZE pCalcSize = (LPNMPGCALCSIZE)lParam; RECT rect = {0}; GetClientRect(pCalcSize->hdr.hwndFrom, &rect); pCalcSize->iWidth = rect.right + 60; pCalcSize->iHeight = rect.bottom; } break; } } default: { ret = DefWindowProc(hwnd, msg, wParam, lParam); } } return ret; } int WINAPI wWinMain(HINSTANCE hInst, HINSTANCE, LPWSTR pCmd, int nShowCmd) { g_hMod = hInst; INITCOMMONCONTROLSEX icex = {sizeof(icex), 0x7FFF}; InitCommonControlsEx(&icex); PCWSTR pClass = L"ComCtlViewer"; WNDCLASSEX wndClass = {sizeof(wndClass), 0}; wndClass.lpfnWndProc = &WndProc; wndClass.lpszClassName = pClass; wndClass.hInstance = hInst; wndClass.hIcon = wndClass.hIconSm = LoadIcon(NULL, IDI_APPLICATION); wndClass.hCursor = LoadCursor(NULL, IDC_ARROW); wndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); ATOM atom = RegisterClassEx(&wndClass); DWORD style = WS_OVERLAPPEDWINDOW | WS_VISIBLE; RECT winRect = {0, 0, 640, 480}; AdjustWindowRectEx(&winRect, style, FALSE, 0); HWND hwnd = CreateWindowEx( 0, pClass, pClass, style, 0, 0, winRect.right - winRect.left, winRect.bottom - winRect.top, NULL, NULL, hInst, NULL ); if(!hwnd) { wprintf(L"Couldn't create window, error %lu\n", GetLastError()); } MSG msg = {0}; while(GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return 0; } int __cdecl wmain(int argc, wchar_t** argv) { CoInitialize(NULL); int ret = 0; EXCEPTION_POINTERS* pEp = NULL; __try { ret = wWinMain(GetModuleHandle(NULL), NULL, GetCommandLine(), SW_SHOWNORMAL); } __except((pEp = GetExceptionInformation()), EXCEPTION_EXECUTE_HANDLER) { wprintf(L"Encountered exception %#x at %#p\n", pEp->ExceptionRecord->ExceptionCode, pEp->ExceptionRecord->ExceptionAddress); HANDLE hFile = CreateFile(L"mem.dmp", GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0x80, NULL); if(hFile == INVALID_HANDLE_VALUE) { wprintf(L"Couldn't create file for dump\n");; } else { MINIDUMP_EXCEPTION_INFORMATION mei = {0}; mei.ThreadId = GetCurrentThreadId(); mei.ExceptionPointers = pEp; mei.ClientPointers = FALSE; MiniDumpWriteDump( GetCurrentProcess(), GetCurrentProcessId(), hFile, MiniDumpWithFullMemory, &mei, NULL, NULL ); CloseHandle(hFile); } } CoUninitialize(); return ret; }