-
September 8th, 2022, 10:43 AM
#1
How to create custom trackbar control appearance(channel,thumb) using Custom Draw?
Hello,
I will state that I am a beginner in WIN32 programming and want to make custom drawing trackbar channel and thumb but without using MFC library, i.e. only with pure WIN32 in C/C++.
According to Customizing the Appearance of CSliderCtrl Using Custom Draw found on CodeProject:
https://www.codeproject.com/Articles...rCtrl-Using-Cu
which unfortunately is using MFC besides the fact it is very well documented. I have searched everywhere and must admit did not find any other solution to this problem. Therefore, I am asking for your willingness to post a simple code example on how to custom draw a trackbar thumb with a dialog and the trackbar would be enough just to understand on how it is done in pure WIN32 by not using MFC.
Just to state that I have done this by using a bitmap as a resource for only changing the appearance of the thumb of the trackbar, and have no idea on how to custom draw it:
Code:
#pragma comment(linker,"\"/manifestdependency:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
#include <string>
#include <Windows.h>
#include <CommCtrl.h>
using namespace std;
HWND window = nullptr;
HWND trackBar = nullptr;
HWND progressBar = nullptr;
HWND staticText = nullptr;
WNDPROC defWndProc = nullptr;
static HBITMAP hBitmapThumb, hBitmapBar;
static BITMAP bm;
LRESULT OnWindowClose(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {
PostQuitMessage(0);
return CallWindowProc(defWndProc, hwnd, message, wParam, lParam);
}
LRESULT OnTrackBarChanged(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {
LRESULT value = SendMessage(trackBar, TBM_GETPOS, 0, 0);
SendMessage(progressBar, PBM_SETPOS, value, 0);
SendMessage(staticText, WM_SETTEXT, 0, (LPARAM)to_wstring(value).c_str());
return CallWindowProc(defWndProc, hwnd, message, wParam, lParam);
}
void DrawBitmapTransparent(HDC hDCDest, int nXDest, int nYDest, int nBitmapWidth, int nBitmapHeight, HBITMAP hBitmap, int nXSrc, int nYSrc, int nTransparentColor)
{
HDC hDCSrc;
HBITMAP hBitmapOld;
HDC hDCMask;
HBITMAP hBitmapMask;
HBITMAP hBitmapMaskOld;
HDC hDCMem;
HBITMAP hBitmapMem;
HBITMAP hBitmapMemOld;
int nBkColorOld;
int nTextColorOld;
BITMAP bm;
GetObject( hBitmap, sizeof( BITMAP ), &bm );
if (!nBitmapWidth) {
nBitmapWidth = bm.bmWidth;
}
if (!nBitmapHeight) {
nBitmapHeight = bm.bmHeight;
}
hDCSrc = CreateCompatibleDC( hDCDest );
hBitmapOld = (HBITMAP)SelectObject( hDCSrc, hBitmap );
hDCMask = CreateCompatibleDC( hDCDest );
hBitmapMask = CreateBitmap( nBitmapWidth, nBitmapHeight, 1, 1, 0 );
hBitmapMaskOld = (HBITMAP)SelectObject( hDCMask, hBitmapMask );
hDCMem = CreateCompatibleDC( hDCDest );
hBitmapMem = CreateCompatibleBitmap( hDCDest, nBitmapWidth, nBitmapHeight );
hBitmapMemOld = (HBITMAP)SelectObject( hDCMem, hBitmapMem );
nBkColorOld = SetBkColor( hDCSrc, nTransparentColor );
BitBlt( hDCMask, 0, 0, nBitmapWidth, nBitmapHeight, hDCSrc, nXSrc, nYSrc, SRCCOPY );
SetBkColor( hDCSrc, nBkColorOld );
nBkColorOld = SetBkColor( hDCDest, RGB(255,255,255) );
nTextColorOld = SetTextColor( hDCDest, RGB(0,0,0) );
BitBlt( hDCMem, 0, 0, nBitmapWidth, nBitmapHeight, hDCDest, nXDest, nYDest, SRCCOPY );
BitBlt( hDCMem, 0, 0, nBitmapWidth, nBitmapHeight, hDCSrc, nXSrc, nYSrc, SRCINVERT );
BitBlt( hDCMem, 0, 0, nBitmapWidth, nBitmapHeight, hDCMask, 0, 0, SRCAND );
BitBlt( hDCMem, 0, 0, nBitmapWidth, nBitmapHeight, hDCSrc, nXSrc, nYSrc, SRCINVERT );
BitBlt( hDCDest, nXDest, nYDest, nBitmapWidth, nBitmapHeight, hDCMem, 0, 0, SRCCOPY );
SetBkColor( hDCDest, nBkColorOld );
SetTextColor( hDCDest, nTextColorOld );
SelectObject( hDCMem, hBitmapMemOld );
DeleteDC( hDCMem );
DeleteObject( hBitmapMem );
SelectObject( hDCMask, hBitmapMaskOld );
DeleteDC( hDCMask );
DeleteObject( hBitmapMask );
SelectObject( hDCSrc, hBitmapOld );
DeleteDC( hDCSrc );
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {
switch(message) {
case WM_NOTIFY:
{
LPNMHDR lpNmhdr = (LPNMHDR)lParam;
if (lpNmhdr->code == NM_CUSTOMDRAW)
{
LPNMCUSTOMDRAW lpNMCustomDraw = (LPNMCUSTOMDRAW)lParam;
if (lpNMCustomDraw->dwDrawStage == CDDS_PREPAINT) {
return CDRF_NOTIFYITEMDRAW;
}
else if (lpNMCustomDraw->dwDrawStage == CDDS_ITEMPREPAINT)
{
long nLeft = lpNMCustomDraw->rc.left;
long nTop = lpNMCustomDraw->rc.top;
long nRight = lpNMCustomDraw->rc.right;
long nBottom = lpNMCustomDraw->rc.bottom;
if (lpNMCustomDraw->dwItemSpec == TBCD_THUMB && hBitmapThumb)
{
long nWidth = nRight - nLeft;
long nHeight = nBottom - nTop;
if (nWidth - bm.bmWidth > 0)
{
nLeft += (nWidth - bm.bmWidth)/2;
nWidth = bm.bmWidth;
}
if (nHeight - bm.bmHeight > 0)
{
nTop += (nHeight - bm.bmHeight)/2;
nHeight = bm.bmHeight;
}
DrawBitmapTransparent(lpNMCustomDraw->hdc , nLeft, nTop, nWidth, nHeight, hBitmapThumb, 0, 0, RGB( 255, 0, 255 ));
return CDRF_SKIPDEFAULT;
}
}
}
}
break;
}
if (message == WM_CLOSE && hwnd == window) return OnWindowClose(hwnd, message, wParam, lParam);
if (message == WM_HSCROLL && hwnd == window && (HWND)lParam == trackBar) return OnTrackBarChanged(hwnd, message, wParam, lParam);
return CallWindowProc(defWndProc, hwnd, message, wParam, lParam);
}
int main() {
window = CreateWindowEx(0, WC_DIALOG, L"TrackBar example", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 300, 300, nullptr, nullptr, nullptr, nullptr);
trackBar = CreateWindowEx(0, TRACKBAR_CLASS, nullptr, WS_CHILD | TBS_HORZ | TBS_BOTTOM | WS_VISIBLE | TBS_FIXEDLENGTH, 150, 10, 250, 70, window, nullptr, nullptr, nullptr);
progressBar = CreateWindowEx(0, PROGRESS_CLASS, nullptr, WS_CHILD | PBS_SMOOTH | WS_VISIBLE, 20, 100, 200, 23, window, nullptr, nullptr, nullptr);
staticText = CreateWindowEx(0, WC_STATIC, L"100", WS_CHILD | WS_VISIBLE, 20, 150, 100, 23, window, nullptr, nullptr, nullptr);
defWndProc = (WNDPROC)SetWindowLongPtr(window, GWLP_WNDPROC, (LONG_PTR)WndProc);
// hBitmapThumb = reinterpret_cast<HBITMAP>(LoadImage(NULL, reinterpret_cast<LPCWSTR>("pink.bmp"), IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE));
hBitmapThumb = (HBITMAP)LoadImage(NULL, (LPCWSTR)L"c:\\Temp\\pink.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
GetObject( hBitmapThumb, sizeof( BITMAP ), &bm );
SendMessage(trackBar, TBM_SETRANGEMIN, 1, 0);
SendMessage(trackBar, TBM_SETRANGEMAX, 1, 200);
SendMessage(trackBar, TBM_SETTHUMBLENGTH, bm.bmWidth/7, 100);
SendMessage(progressBar, PBM_SETRANGE32, 0, 200);
SendMessage(progressBar, PBM_SETPOS, 100, 0);
ShowWindow(window, SW_SHOW);
MSG message = { 0 };
while (GetMessage(&message, nullptr, 0, 0))
DispatchMessage(&message);
}
I am very thankful to anyone who participates towards solving my problem.
-
September 8th, 2022, 02:19 PM
#2
Re: How to create custom trackbar control appearance(channel,thumb) using Custom Draw
Well, MFC is just a wrapper around the plain Win32 API. So you could slightly modify the code from https://www.codeproject.com/Articles...rCtrl-Using-Cu removing the MFC parts and/or change it to raw Win32.
For instance the code in
Code:
void CCustomDrawSliderCtrl::OnReflectedCustomDraw(NMHDR* pNMHDR, LRESULT* pResult)
after some changes you could place in your CALLBACK WndProc under the case of
Code:
if (lpNmhdr->code == NM_CUSTOMDRAW)
Victor Nijegorodov
Tags for this Thread
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|