返回介绍

Custom controls in Windows API

发布于 2025-02-22 22:19:24 字数 5472 浏览 0 评论 0 收藏 0

Here we will demonstrate, how to create our own custom controls. Windows API has a collection of various prebuilt controls. More specific controls have to be created manually. We use the GDI to create custom controls.

The Burning control

This control can be found in various media burning applications, like Nero Burning ROM.

#include <windows.h>
#include <commctrl.h>
#include <wchar.h>


LRESULT CALLBACK PanelProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);


HINSTANCE g_hinst;
LRESULT g_pos = 150;


int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, 
          PWSTR lpCmdLine, int nCmdShow)
{
  HWND hwnd;
  MSG  msg;  
  WNDCLASSW wc = {0};

  wc.lpszClassName = L"Application";
  wc.hInstance   = hInstance;
  wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
  wc.lpfnWndProc   = WndProc;
  wc.hCursor     = LoadCursor(0, IDC_ARROW);

  g_hinst = hInstance;
  
  RegisterClassW(&wc);
  hwnd = CreateWindowW(wc.lpszClassName, L"Burning control",
        WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_CLIPCHILDREN,
        100, 100, 400, 250, 0, 0, hInstance, 0);  

  while( GetMessage(&msg, NULL, 0, 0)) {
  DispatchMessage(&msg);
  }

  return (int) msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, 
  WPARAM wParam, LPARAM lParam)
{

  static HWND hwndTrack, hwndBurn;
  WNDCLASSW rwc = {0};
 
  INITCOMMONCONTROLSEX InitCtrlEx;

  InitCtrlEx.dwSize = sizeof(INITCOMMONCONTROLSEX);
  InitCtrlEx.dwICC  = ICC_BAR_CLASSES;
  InitCommonControlsEx(&InitCtrlEx);

  switch(msg)  
  {
    case WM_CREATE:
         
      rwc.lpszClassName = L"BurningControl";

      rwc.hbrBackground = GetSysColorBrush(COLOR_BTNFACE);
      rwc.style     = CS_HREDRAW;
      rwc.lpfnWndProc   = PanelProc;
      rwc.hCursor     = LoadCursor(0, IDC_ARROW);
      RegisterClassW(&rwc);

      hwndBurn = CreateWindowExW(WS_EX_STATICEDGE , L"BurningControl", NULL,
        WS_CHILD | WS_VISIBLE, 0, 330, 490, 30, hwnd, (HMENU)1, NULL, NULL);

      hwndTrack = CreateWindowExW(0, TRACKBAR_CLASSW, NULL,
        WS_CHILD | WS_VISIBLE | TBS_FIXEDLENGTH | TBS_NOTICKS,
        40, 25, 150, 25, hwnd, (HMENU) 2, g_hinst, NULL);

      SendMessage(hwndTrack, TBM_SETRANGE,  TRUE,  MAKELONG(0, 750));
      SendMessage(hwndTrack, TBM_SETPAGESIZE, 0,  20); 
      SendMessage(hwndTrack, TBM_SETTICFREQ, 20, 0); 
      SendMessage(hwndTrack, TBM_SETPOS, TRUE, 150);  
      break;

    case WM_SIZE:

      SetWindowPos(hwndBurn, NULL, 0, HIWORD(lParam)-30, 
        LOWORD(lParam), 30, SWP_NOZORDER);
      break;

    case WM_HSCROLL:

      g_pos = SendMessage(hwndTrack, TBM_GETPOS, 0, 0);
      InvalidateRect(hwndBurn, NULL, TRUE);
      break;      

    case WM_DESTROY:

      PostQuitMessage(0);
      break; 
  }

  return DefWindowProcW(hwnd, msg, wParam, lParam);
}


LRESULT CALLBACK PanelProc(HWND hwnd, UINT msg, 
  WPARAM wParam, LPARAM lParam)
{
  HBRUSH hBrushYellow, hBrushRed, holdBrush;
  HPEN hPen, holdPen;
  HFONT hFont, holdFont;
  PAINTSTRUCT ps;
  RECT rect, rect2;
  
  wchar_t *cap[] = { L"75", L"150", L"225", L"300", L"375", L"450", 
    L"525", L"600", L"675"};

  HDC hdc;
  int till;
  int step, full;
  int i;

  switch(msg)  
  {
  case WM_PAINT:
  
    hdc = BeginPaint(hwnd, &ps);

    GetClientRect(hwnd, &rect);

    till = (rect.right / 750.0) * g_pos;
    step = rect.right / 10.0;
    full = (rect.right / 750.0) * 700;
    
    hBrushYellow = CreateSolidBrush(RGB(255, 255, 184));
    hBrushRed = CreateSolidBrush(RGB(255, 110, 110));

    hPen = CreatePen(PS_NULL, 1, RGB(0, 0, 0));
    holdPen = SelectObject(hdc, hPen);

    hFont = CreateFontW(13, 0, 0, 0, FW_MEDIUM, 0, 0, 0, 0, 
        0, 0, 0, 0, L"Tahoma");

    holdFont = SelectObject(hdc, hFont);
    
    if(till > full) {
    
      SelectObject(hdc, hBrushYellow);
      Rectangle(hdc, 0, 0, full, 30);
      holdBrush = SelectObject(hdc, hBrushRed);
      Rectangle(hdc, full, 0, till, 30);

    } else {
    
      holdBrush = SelectObject(hdc, hBrushYellow);
      Rectangle(hdc, 0, 0, till, 30);
    }

    SelectObject(hdc, holdPen);

    for ( i = 1; i < 10; i++) {

      MoveToEx(hdc, i*step, 0, NULL);
      LineTo(hdc, i*step, 7);

      rect2.bottom = 28;
      rect2.top = 8;
      rect2.left = i*step-10;
      rect2.right = i*step+10;

      SetBkMode(hdc, TRANSPARENT) ;
      DrawTextW(hdc, cap[i-1], wcslen(cap[i-1]), &rect2, DT_CENTER);
    }

    SelectObject(hdc, holdBrush);
    DeleteObject(hBrushYellow);
    DeleteObject(hBrushRed);

    DeleteObject(hPen);

    SelectObject(hdc, holdFont);
    DeleteObject(hFont);
          
    EndPaint(hwnd, &ps);
    break;
  }

  return DefWindowProcW(hwnd, msg, wParam, lParam);
}

In our example, we display a trackbar control and our custom burning control. The trackbar control is used to control the state of the burning control.

The burning control is a simple window. It is placed on the bottom of the parent window. It is completely drawn during the WM_PAINT message. The lines, text, and background is drawn using the GDI function calls.

Burning control
Figure: Burning control

In this part of the Windows API tutorial, we have created a Burning custom control.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文