/** * @file * @brief QWIN GUI facilities for building realistic embedded front panels * @cond ****************************************************************************** * Last updated for version 6.6.0 * Last updated on 2019-07-30 * * Q u a n t u m L e a P s * ------------------------ * Modern Embedded Software * * Copyright (C) 2005-2019 Quantum Leaps, LLC. All rights reserved. * * This program is open source software: you can redistribute it and/or * modify it under the terms of the GNU General Public License as published * by the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Alternatively, this program may be distributed and modified under the * terms of Quantum Leaps commercial licenses, which expressly supersede * the GNU General Public License and are specifically designed for * licensees interested in retaining the proprietary status of their code. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * Contact information: * * ****************************************************************************** * @endcond */ #include "qwin_gui.h" #include static HWND l_hWnd; static HDC l_hDC; /*--------------------------------------------------------------------------*/ HWND CreateCustDialog(HINSTANCE hInst, int iDlg, HWND hParent, WNDPROC lpfnWndProc, LPCTSTR lpWndClass) { WNDCLASSEX wndclass; wndclass.cbSize = sizeof(wndclass); wndclass.style = CS_HREDRAW | CS_VREDRAW; wndclass.lpfnWndProc = lpfnWndProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = DLGWINDOWEXTRA; wndclass.hInstance = hInst; wndclass.hIcon = NULL; wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); wndclass.hbrBackground = (HBRUSH)COLOR_WINDOW; wndclass.lpszMenuName = NULL; wndclass.lpszClassName = lpWndClass; wndclass.hIconSm = NULL; RegisterClassEx(&wndclass); l_hWnd = CreateDialog(hInst, MAKEINTRESOURCE(iDlg), hParent, NULL); l_hDC = GetDC(l_hWnd); /* obtain the DC for the client area of the window */ /* NOTE: WM_INITDIALOG provides stimulus for initializing dialog controls. * Dialog box procedures typically use this message to initialize controls * and carry out any other initialization tasks that affect the appearance * of the dialog box. */ SendMessage(l_hWnd, WM_INITDIALOG, (WPARAM)0, (LPARAM)0); return l_hWnd; } /*--------------------------------------------------------------------------*/ void OwnerDrawnButton_init(OwnerDrawnButton * const me, UINT itemID, HBITMAP hBitmapUp, HBITMAP hBitmapDwn, HCURSOR hCursor) { me->itemID = itemID; me->hBitmapUp = hBitmapUp; me->hBitmapDown = hBitmapDwn; me->hCursor = hCursor; me->isDepressed = 0; } /*..........................................................................*/ void OwnerDrawnButton_xtor(OwnerDrawnButton * const me) { DeleteObject(me->hBitmapUp); DeleteObject(me->hBitmapDown); DeleteObject(me->hCursor); } /*..........................................................................*/ enum OwnerDrawnButtonAction OwnerDrawnButton_draw( OwnerDrawnButton * const me, LPDRAWITEMSTRUCT lpdis) { enum OwnerDrawnButtonAction ret = BTN_NOACTION; if ((lpdis->itemAction & ODA_DRAWENTIRE) != 0U) { if (me->hCursor != NULL) { SetClassLongPtr(lpdis->hwndItem, GCLP_HCURSOR, (LONG_PTR)me->hCursor); me->hCursor = NULL; /* mark the cursor set */ } DrawBitmap(lpdis->hDC, me->hBitmapUp, lpdis->rcItem.left, lpdis->rcItem.top); me->isDepressed = 0; ret = BTN_PAINTED; } else if ((lpdis->itemAction & ODA_SELECT) != 0U) { if ((lpdis->itemState & ODS_SELECTED) != 0U) { DrawBitmap(lpdis->hDC, me->hBitmapDown, lpdis->rcItem.left, lpdis->rcItem.top); me->isDepressed = !0; ret = BTN_DEPRESSED; } else { /* NOTE: the bitmap for button "UP" look will be * drawn in the ODA_DRAWENTIRE action */ me->isDepressed = 0; ret = BTN_RELEASED; } } return ret; } /*..........................................................................*/ void OwnerDrawnButton_set(OwnerDrawnButton * const me, int isDepressed) { if (me->isDepressed != isDepressed) { HWND hItem = GetDlgItem(l_hWnd, me->itemID); me->isDepressed = isDepressed; if (isDepressed) { DrawBitmap(GetDC(hItem), me->hBitmapDown, 0, 0); } else { DrawBitmap(GetDC(hItem), me->hBitmapUp, 0, 0); } } } /*..........................................................................*/ BOOL OwnerDrawnButton_isDepressed(OwnerDrawnButton const * const me) { return me->isDepressed; } /*--------------------------------------------------------------------------*/ void GraphicDisplay_init(GraphicDisplay * const me, UINT width, UINT height, UINT itemID, BYTE const bgColor[3]) { BITMAPINFO bi24BitInfo; RECT rect; me->src_width = width; me->src_height = height; me->hItem = GetDlgItem(l_hWnd, itemID); me->dst_hDC = GetDC(me->hItem); GetWindowRect(me->hItem, &rect); me->dst_width = rect.right - rect.left; me->dst_height = rect.bottom - rect.top; me->bgColor[0] = bgColor[0]; me->bgColor[1] = bgColor[1]; me->bgColor[2] = bgColor[2]; bi24BitInfo.bmiHeader.biBitCount = 3U*8U; /* 3 RGB bytes */ bi24BitInfo.bmiHeader.biCompression = BI_RGB; /* RGB color */ bi24BitInfo.bmiHeader.biPlanes = 1U; bi24BitInfo.bmiHeader.biSize = sizeof(bi24BitInfo.bmiHeader); bi24BitInfo.bmiHeader.biWidth = me->src_width; bi24BitInfo.bmiHeader.biHeight = me->src_height; me->src_hDC = CreateCompatibleDC(me->dst_hDC); me->hBitmap = CreateDIBSection(me->src_hDC, &bi24BitInfo, DIB_RGB_COLORS, (void **)&me->bits, 0, 0); SelectObject(me->src_hDC, me->hBitmap); GraphicDisplay_clear(me); GraphicDisplay_redraw(me); } /*..........................................................................*/ void GraphicDisplay_xtor(GraphicDisplay * const me) { DeleteDC(me->src_hDC); DeleteObject(me->hBitmap); OutputDebugString("GraphicDisplay_xtor\n"); } /*..........................................................................*/ void GraphicDisplay_clear(GraphicDisplay * const me) { UINT n; BYTE r = me->bgColor[0]; BYTE g = me->bgColor[1]; BYTE b = me->bgColor[2]; BYTE *bits = me->bits; for (n = me->src_width * me->src_height; n != 0U; --n, bits += 3) { bits[0] = b; bits[1] = g; bits[2] = r; } } /*..........................................................................*/ void GraphicDisplay_redraw(GraphicDisplay * const me) { StretchBlt(me->dst_hDC, 0, 0, me->dst_width, me->dst_height, me->src_hDC, 0, 0, me->src_width, me->src_height, SRCCOPY); } /* SegmentDisplay ----------------------------------------------------------*/ void SegmentDisplay_init(SegmentDisplay * const me, UINT segmentNum, UINT bitmapNum) { UINT n; me->hSegment = (HWND *)calloc(segmentNum, sizeof(HWND)); me->segmentNum = segmentNum; for (n = 0U; n < segmentNum; ++n) { me->hSegment[n] = NULL; } me->hBitmap = (HBITMAP *)calloc(bitmapNum, sizeof(HBITMAP)); me->bitmapNum = bitmapNum; for (n = 0U; n < bitmapNum; ++n) { me->hBitmap[n] = NULL; } } /*..........................................................................*/ void SegmentDisplay_xtor(SegmentDisplay * const me) { UINT n; for (n = 0U; n < me->segmentNum; ++n) { DeleteObject(me->hSegment[n]); } free(me->hSegment); for (n = 0U; n < me->bitmapNum; ++n) { DeleteObject(me->hBitmap[n]); } free(me->hBitmap); } /*..........................................................................*/ BOOL SegmentDisplay_initSegment(SegmentDisplay * const me, UINT segmentNum, UINT segmentID) { if (segmentNum < me->segmentNum) { me->hSegment[segmentNum] = GetDlgItem(l_hWnd, segmentID); return me->hSegment[segmentNum] != NULL; } else { return FALSE; } } /*..........................................................................*/ BOOL SegmentDisplay_initBitmap(SegmentDisplay * const me, UINT bitmapNum, HBITMAP hBitmap) { if ((bitmapNum < me->bitmapNum) && (hBitmap != NULL)) { me->hBitmap[bitmapNum] = hBitmap; return TRUE; } else { return FALSE; } } /*..........................................................................*/ BOOL SegmentDisplay_setSegment(SegmentDisplay * const me, UINT segmentNum, UINT bitmapNum) { if ((segmentNum < me->segmentNum) && (bitmapNum < me->bitmapNum)) { SendMessage(me->hSegment[segmentNum], STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)me->hBitmap[bitmapNum]); return TRUE; } else { return FALSE; } } /*--------------------------------------------------------------------------*/ /* DrawBitmap() function adapted from the book "Programming Windows" by * Charles Petzold. */ void DrawBitmap(HDC hdc, HBITMAP hBitmap, int xStart, int yStart) { BITMAP bm; POINT ptSize, ptOrg; HDC hdcMem = CreateCompatibleDC(hdc); SelectObject(hdcMem, hBitmap); SetMapMode(hdcMem, GetMapMode(hdc)); GetObject(hBitmap, sizeof(BITMAP), (LPVOID)&bm); ptSize.x = bm.bmWidth; ptSize.y = bm.bmHeight; DPtoLP(hdc, &ptSize, 1); ptOrg.x = 0; ptOrg.y = 0; DPtoLP(hdcMem, &ptOrg, 1); BitBlt(hdc, xStart, yStart, ptSize.x, ptSize.y, hdcMem, ptOrg.x, ptOrg.y, SRCCOPY); DeleteDC(hdcMem); }