/************************************************************************ * * File: TabWindow.cpp * * Description: * * * This file is part of the Microsoft Windows SDK Code Samples. * * Copyright (C) Microsoft Corporation. All rights reserved. * * This source code is intended only as a supplement to Microsoft * Development Tools and/or on-line documentation. See these other * materials for detailed information regarding Microsoft code samples. * * THIS CODE AND INFORMATION ARE PROVIDED AS IS WITHOUT WARRANTY OF ANY * KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A * PARTICULAR PURPOSE. * ************************************************************************/ #include "DWriteHelloWorld.h" /****************************************************************** * * * TabWindow::TabWindow constructor * * * * Initialize member data * * * ******************************************************************/ TabWindow::TabWindow() : hwnd_(NULL), hwndTab_(NULL), hwndChild_(NULL) { } /****************************************************************** * * * TabWindow::~TabWindow destructor * * * * Tear down resources * * * ******************************************************************/ TabWindow::~TabWindow() { } /****************************************************************** * * * TabWindow::Initialize * * * * Create application window and device-independent resources * * * ******************************************************************/ HRESULT TabWindow::Initialize() { WNDCLASSEX wcex; HRESULT hr; ATOM atom; // Register window class. wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = TabWindow::WndProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = sizeof(LONG_PTR); wcex.hInstance = HINST_THISCOMPONENT; wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); wcex.lpszMenuName = NULL; wcex.hIcon = LoadIcon( NULL, IDI_APPLICATION); wcex.hCursor = LoadCursor( NULL, IDC_ARROW); wcex.lpszClassName = TEXT("TabWindow"); wcex.hIconSm = LoadIcon( NULL, IDI_APPLICATION ); atom = RegisterClassEx( &wcex ); hr = atom ? S_OK : E_FAIL; hwnd_ = CreateWindow( TEXT("TabWindow"), TEXT("Direct Write samples"), WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS, CW_USEDEFAULT, CW_USEDEFAULT, 640, 480, NULL, NULL, HINST_THISCOMPONENT, this ); if (SUCCEEDED(hr)) { hr = hwnd_ ? S_OK : E_FAIL; } // Initialize tabs. hwndTab_ = CreateTabControl(); if (hwndTab_ == NULL) { hr = E_FAIL; } // Initialize child windows. if (SUCCEEDED(hr)) { hr = CreateChildWindows(); } ShowWindow( hwnd_, SW_SHOWNORMAL ); UpdateWindow( hwnd_ ); return hr; } HWND TabWindow::CreateTabControl() { RECT rcClient; HWND hwndTab; TCITEM tie; const wchar_t* tab1Label = TEXT("Simple Text"); const wchar_t* tab2Label = TEXT("Multiformatted Text"); const wchar_t* tab3Label = TEXT("Custom Text Renderer"); // Get the dimensions of the parent window's client area, and // create a tab control child window of that size. GetClientRect(hwnd_, &rcClient); InitCommonControls(); hwndTab = CreateWindowEx(0, WC_TABCONTROL, TEXT(""), WS_CHILD | WS_CLIPSIBLINGS | WS_VISIBLE, 0, 0, rcClient.right, rcClient.bottom, hwnd_, NULL, HINST_THISCOMPONENT, NULL); if (hwndTab == NULL) { return NULL; } // Add tabs. tie.mask = TCIF_TEXT | TCIF_IMAGE; tie.iImage = -1; tie.pszText = (LPWSTR) tab1Label; if (TabCtrl_InsertItem(hwndTab, 0, &tie) == -1) { DestroyWindow(hwndTab); return NULL; } tie.pszText = (LPWSTR) tab2Label; if (TabCtrl_InsertItem(hwndTab, 1, &tie) == -1) { DestroyWindow(hwndTab); return NULL; } tie.pszText = (LPWSTR) tab3Label; if (TabCtrl_InsertItem(hwndTab, 2, &tie) == -1) { DestroyWindow(hwndTab); return NULL; } return hwndTab; } HRESULT TabWindow::CreateChildWindows() { HRESULT hr; hr = simpleText_.Initialize(hwnd_); if (SUCCEEDED(hr)) { hr = multiformattedText_.Initialize(hwnd_); } if (SUCCEEDED(hr)) { hr = customText_.Initialize(hwnd_); } hwndChild_ = simpleText_.GetHwnd(); return hr; } /****************************************************************** * * * TabWindow::OnPaint * * * * Called whenever the application needs to display the client * * window. * * * ******************************************************************/ HRESULT TabWindow::OnPaint(const PAINTSTRUCT &ps) { HRESULT hr = S_OK; return hr; } /****************************************************************** * * * TabWindow::OnResize * * * * If the application receives a WM_SIZE message * * * ******************************************************************/ void TabWindow::OnResize(UINT width, UINT height) { HDWP hdwp; RECT rc; // Calculate the display rectangle, assuming the // tab control is the size of the client area. SetRect(&rc, 0, 0, width, height); TabCtrl_AdjustRect(hwndTab_, FALSE, &rc); // Size the tab control to fit the client area. hdwp = BeginDeferWindowPos(2); DeferWindowPos(hdwp, hwndTab_, NULL, 0, 0, width, height, SWP_NOMOVE | SWP_NOZORDER ); // Position and size the child window // and make sure the // it is in front of the tab control. DeferWindowPos(hdwp, hwndChild_, HWND_TOP, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, 0 ); EndDeferWindowPos(hdwp); } /****************************************************************** * * * TabWindow::WndProc * * * * Window message handler * * * ******************************************************************/ LRESULT CALLBACK TabWindow::WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { if (message == WM_CREATE) { LPCREATESTRUCT pcs = (LPCREATESTRUCT)lParam; TabWindow *pTabWindow = (TabWindow *)pcs->lpCreateParams; ::SetWindowLongPtrW( hwnd, GWLP_USERDATA, PtrToUlong(pTabWindow)); return 1; } TabWindow *pTabWindow = reinterpret_cast( ::GetWindowLongPtr(hwnd, GWLP_USERDATA)); if (pTabWindow) { switch(message) { case WM_SIZE: { UINT width = LOWORD(lParam); UINT height = HIWORD(lParam); pTabWindow->OnResize(width, height); } return 0; case WM_PAINT: case WM_DISPLAYCHANGE: { PAINTSTRUCT ps; BeginPaint(hwnd, &ps); pTabWindow->OnPaint( ps ); EndPaint( hwnd, &ps ); } return 0; case WM_ERASEBKGND: return true; case WM_NOTIFY: switch (((LPNMHDR)lParam)->code) { case TCN_SELCHANGE: { int selection = TabCtrl_GetCurSel(pTabWindow->hwndTab_); // Hide the current child window. ShowWindow(pTabWindow->hwndChild_, SW_HIDE); // Get the handle to the new child window to display. switch (selection) { case 0: { pTabWindow->hwndChild_ = pTabWindow->simpleText_.GetHwnd(); break; } case 1: { pTabWindow->hwndChild_ = pTabWindow->multiformattedText_.GetHwnd(); break; } case 2: { pTabWindow->hwndChild_ = pTabWindow->customText_.GetHwnd(); break; } } // Show the new child window. ShowWindow(pTabWindow->hwndChild_, SW_SHOWNORMAL); // Get the current window dimensions and have the main window // resize the child window to fit it in the area below the tab control. // // This is required for the first time a new child is displayed to prevent // it from overlapping the tab control. RECT rect; GetClientRect(hwnd, &rect); pTabWindow->OnResize(rect.right - rect.left, rect.bottom - rect.top); } } return 0; case WM_DESTROY: { PostQuitMessage(0); } return 1; } } return DefWindowProc( hwnd, message, wParam, lParam ); }