Implementing Custom trackbar thumb color and shape issues...

12 views
Skip to first unread message

Ognen

unread,
Sep 27, 2022, 8:43:51 AM9/27/22
to FilterMeister Mailing List (FMML)
Hi all,

I am currently trying to change the trackbar thumb by implementing a bitmap transparency, so the color and the shape of the thumb can be formed. I working with the code of AfhFM109h-sourcecode-20211231, i.e. the FilterMeister editor, the PS plugin.

While debugging in VS, I am having few issues that have to cope with. First, I am trying to understand why there is not any data allocated in hBitmapThumb, i.e. the .bmp does not load. Second, when trying to exit Photoshop after exiting FM plugin, the window of PS is totally freezed, and the last, when trying to load a control right below my custom function in this order:

%fml
CustomTrackbarThumb();
ctl(0):trackbar

Photoshop crashes.

Here's the code I am trying to implement.

HWND trackBar = NULL;
WNDPROC defWndProc = NULL;

static HBITMAP hBitmapThumb;
static BITMAP bm;

LRESULT OnWindowClose(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {
    PostQuitMessage(0);
    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 == fmc.hDlg) return OnWindowClose(hwnd, message, wParam, lParam);
    return CallWindowProc(defWndProc, hwnd, message, wParam, lParam);
}

INT_PTR fm_CustomTrackbarThumb(void) {
    trackBar = CreateWindowEx(0, TRACKBAR_CLASS, "", WS_CHILD | TBS_HORZ | TBS_BOTTOM | WS_VISIBLE, 1, 1, 250, 20, fmc.hDlg, NULL, hDllInstance, NULL);

    defWndProc = (WNDPROC)SetWindowLongPtr(fmc.hDlg, GWLP_WNDPROC, (LONG_PTR)WndProc);

    hBitmapThumb = (HBITMAP)LoadImage(hDllInstance, (LPCWSTR)L"c:\\temp\\pink.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
    GetObject( hBitmapThumb, sizeof( BITMAP ), &bm );

    SendMessage(trackBar, TBM_SETTIPSIDE, bm.bmWidth/7, 100);

    MSG message = { 0 };
    while (GetMessage(&message, NULL, 0, 0))
    DispatchMessage(&message);
}

There are various reasons on why I chose to edit this code, and one of them is that in Harald Heim's VS version of FM the scripting of the controls is having issues, they do not show in the actions panel and also when converting a layer to a SmartFilter, the compiled plugin is greyed out, i.e. disabled.

I did not choose to implement Nuklear nor ImGUI due to many issues coming between the GUI libraries and FM code itself.

Any guidance for this would be appreciated.

Ognen

unread,
Sep 27, 2022, 8:50:57 AM9/27/22
to FilterMeister Mailing List (FMML)
A note on the code above, it is just a prototype and it cannot be used as real control yet all because there are certain things that have to be done before making it usable.

Ognen

unread,
Sep 28, 2022, 6:28:40 AM9/28/22
to FilterMeister Mailing List (FMML)
new_thumb.png

Ognen

unread,
Sep 28, 2022, 6:30:23 AM9/28/22
to FilterMeister Mailing List (FMML)
I have successfully replaced the thumb(made it similar to PS's default) with the Windows's default(see the picture above) by reimplementing the code into createCtl() function. I will not post the code for every change, but the problem with the bitmap not loading was in the L literal used in front of the string which I have removed (obviously FM wants 8 bit storage):
hBitmapThumb = (HBITMAP)LoadImage(hDllInstance, (LPCWSTR)"c:\\Temp\\pink.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);

and also removed the next lines to unfreeze Photoshop:

 ShowWindow(window, SW_SHOW);


 MSG message = { 0 };
 while (GetMessage(&message, NULL, 0, 0))
 DispatchMessage(&message);

The next problem is, when compiling the plug-in trying to load, the dialog does not show at all and Photoshop freezes, and by pressing Alt+F4 it looks like it is closed and Photoshop is unfreezed. It's just like an invisible dialog.
Reply all
Reply to author
Forward
0 new messages