Plugin.dll sliders in FilterFactory 3.0.4

Back to technical analysis page

Filter Factory 3.0.4 will draw sliders using the Photoshop library Plugin.dll while Filter Factory 3.00 drew the sliders with custom code (and was therefore independent from Photoshop!).

This page explains all slider methods in Plugin.dll and how to use them programmatically (Language C++ as example).

PS7 plugins using Plugin.dll sliders

Examples

Download a Visual Studio test project working with sliders!

Example for working with a slider (C++)

This example draws a slider with the range 0 to 100, and the message loop of the window will print the slider's thumb position in the window caption.

#include "Photoshop_Sliders.h"

#define CTL_SLIDER1 123

DWORD gSliderMsgId = 0;

void initWindow() {
	_LoadPluginDll();
	RegisterSlider(hInstance, &gSliderMsgId);
	CreateWindowW(L"Slider", L"", WS_CHILD | WS_VISIBLE | WS_HORIZONTAL_SLIDER, 10, 10, 600, 40, hWnd, (HMENU)CTL_SLIDER1, hInstance, 0);
	SetSliderRange(GetDlgItem(hWnd, CTL_SLIDER1), 0, 100);
	SetSliderPos(GetDlgItem(hWnd, CTL_SLIDER1), 50, true);
}

void destroyWindow() {
	UnRegisterSlider(hInstance);
	_UnloadPluginDll();
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
	if (gSliderMsgId != 0 && message == gSliderMsgId) {
		if (wParam == CTL_SLIDER1) {
			if (SLIDER_EVENT(lParam) == SliderEventMoved) {
				char x[100];
				sprintf(x, "Position = %d", SLIDER_POS(lParam));
				SetWindowTextA(hWnd, x);
			}
		}

	}
	// ... here is the rest of your WndProc ...
}

Slider functions in Plugin.dll of Photoshop 7

The following definitions have also been checked with the 64 bit version of Plugin.dll in Photoshop 2024. The PLUGIN.DLL sliders have been used in the Project Filter Foundry.

Photoshop_Sliders.h (C++ headers)

#ifndef PHOTOSHOP_SLIDERS_H_
#define PHOTOSHOP_SLIDERS_H_

// These additional window styles can be set when a "Slider" class control is added by CreateWindowW().
#define WS_HORIZONTAL_SLIDER 0
#define WS_VERTICAL_SLIDER 0x1000

// These are macros help you with checking lParam of the slider windows message
#define SLIDER_EVENT(lParam) ((PluginDllSliderEventType)(((lParam) >> 16) & 0xFFFF))
#define SLIDER_POS(lParam) ((int16_t)((lParam) & 0xFFFF))
typedef enum PluginDllSliderEventType_ {
	SliderEventMoved = 0x7FFB,
	SliderEventReleased = 0x7FFC,
	SliderEventIdle = 0x7FFD,
	SliderEventIdleOnce = 0x7FFE
} PluginDllSliderEventType;

// This method will register the "Slider" class used in dialogs.
// Called by Filter Factory like this: RegisterSlider(PTR DS:[1C008000h], PTR DS:[1C008010h]);
// The message ID returned will be used to receive slider updates
// It is calculated this way:  outMessageID=RegisterWindowMessageA("PSSlCmd")
// Attention: This function might fail if a previous UnRegisterSlider was forgotten or failed.
BOOL __cdecl RegisterSlider(HINSTANCE hInstanceDll, DWORD* outMessageID);

// This method will unregister the "Slider" class used in dialogs.
// This method MUST be called, otherwise other calls to RegisterSlider() might fail
BOOL __cdecl UnRegisterSlider(HINSTANCE hInstanceDll);

// Internal method. Allocates and initializes the data of data to the handle "PSSlData".
void __cdecl AllocSlider(HWND hWnd);

// Internal method. This makes sure that PSSlData is freed from memory
// The slider calls it itself when it receives the message WM_QUIT.
void __cdecl FreeSlider(HWND hWnd);

// This method will receive the slider position in either its value or measured with pixels.
// If bPixelPosition=TRUE, then return the position in pixels
// If bPixelPosition=FALSE, then return the position as value
// Instead of using the DLL API, you can send the custom windows message 0x4CD which results in a call of "return GetSliderPos(hWnd, wParam);"
int __cdecl GetSliderPos(HWND hWnd, BOOL bPixelPosition);

// This method will set the position of a slider. dlgitem can be retrieved with GetDlgItem(hDlg, ID_SLIDER1)
// Instead of using the DLL API, you can send the custom windows message 0x4CC which results in a call of SetSliderPos(hWnd, wParam, 1);
void __cdecl SetSliderPos(HWND dlgitem, int nPos, BOOL bRepaint);

// Returns the current slider value. Lower 16 bit = lower range. Upper 16 bit = upper range.
// Instead of using the DLL API, you can send the custom windows message 0x4CE which results in a call of "return GetSliderRange(hWnd);"
typedef struct SliderRange_ {
	union {
		uint32_t raw;  // raw == (upper&0xFFFF << 16) | lower
		struct {
			int16_t lower;
			int16_t upper;
		};
	};
} SliderRange;
SliderRange __cdecl GetSliderRange(HWND hWnd);

// This method will set the range of a slider. dlgitem can be retrieved with GetDlgItem(hDlg, ID_SLIDER1)
// Instead of using the DLL API, you can send the custom windows message 0x4CF which results in a call of SetSliderRange(hWnd, lParam&0xFFFF, lParam>>16);
void __cdecl SetSliderRange(HWND dlgitem, int nMin, int nMax);

// Call LockSliderData() to receive the current data of the slider,
// and call UnlockSliderData() afterwards. It will be called by the slider
// itself, so it usually doesn't need to be called manually.
typedef struct SliderData_ SliderData; // forward declaration
typedef void(__cdecl f_SliderProc)(HWND hWnd, HDC dc, SliderData* sliderData);
typedef struct ThumbSize_ {
	union {
		uint32_t raw;  // (raw == height&0xFFFF << 16) | width
		struct {
			uint16_t width;
			uint16_t height;
		};
	};
} ThumbSize;
typedef struct SliderData_ { // GetPropA of "PSSlData"
	//                         32bit 64bit
	HWND hWnd;               //  0x0  0x0 ... initialized by AllocSlider
	BOOL verticalSlider;     //  0x4  0x8 ... initialized by AllocSlider as follows: 1 if WS_VERTICAL_SLIDER is in GWL_STYLE, otherwise 0.
	int32_t rangeMin;        //  0x8  0xC ... Min range. Initialized by AllocSlider with value 0.
	int32_t rangeMax;        //  0xC 0x10 ... Max range. initialized by AllocSlider with value 0x14.
	uint32_t pixelPosition;  // 0x10 0x14 ... initialized by AllocSlider as 5 (horizontal slider) or 7 (vertical slider).
	int32_t sliderPosition;  // 0x14 0x18 ... initialized by AllocSlider with value 0.
	int32_t thumbOffset;     // 0x18 0x1C ... Written by SetSliderThumbOff(). Does not work with modern versions of Plugin.dll (see notes below).
	ThumbSize thumbSize;     // 0x1C 0x20 ... Written by SetSliderThumbSize(). Does not work with modern versions of Plugin.dll (see notes below).
	uint32_t flags;          // 0x20 0x24 ... Flags set by SetSliderFlags(). Initialized by AllocSlider() with 0.
	void* additionalData;    // 0x24 0x28 ... Additional "data", set by SetSliderData(). Initialized by AllocSlider(). Not used by the API.
	f_SliderProc* proc2;     // 0x28 0x30 ... SliderProc "2", set by SetSliderProc(hWnd,proc,FALSE). By default occupied with DefPlotThumb(). Called by PaintSlider() after "1". Initialized by AllocSlider with NULL.
	f_SliderProc* proc1;     // 0x2C 0x38 ... SliderProc "1", set by SetSliderProc(hWnd,proc,TRUE). By default occupied by DefPaintBack(). Called by PaintSlider() before "2". Initialized by AllocSlider with NULL.
	SliderData* ptrSlMin;    // 0x30 0x40 ... pointer to min slider's PSSlData; set by SetSliderMin(). Initialized by AllocSlider() with NULL.
	SliderData* ptrSlMax;    // 0x34 0x48 ... pointer to max slider's PSSlData; set by SetSliderMax(). Initialized by AllocSlider() with NULL.
} SliderData; // Size 32 bit = 56 bytes, Size 64 bit = 80 bytes
SliderData* __cdecl LockSliderData(HWND hWnd);

// Unlocks slider data that has been locked previously by LockSliderData().
void __cdecl UnlockSliderData(HWND hWnd);

// Calls proc1 and proc2 if previously set by SetSliderProc().
void __cdecl PaintSlider(HWND hWnd, HDC dc);

// Sets additional data for the slider
// Instead of using the DLL API, you can send the custom windows message 0x4C9 which results in a call of SetSliderData(hWnd, lParam);
void __cdecl SetSliderData(HWND hWnd, void* additionalData);

// This flag is used by the internal method DragThumb() in PS3, PS7 and PS2024.
// If the flag is set, the slider will automatically snap to the nearest logical position (while dragging).
// If the flag is unset, then the snapping will occur once the cursor is released.
// Note that the event type `SliderEventMoved` will be fired even if the slider does not snap,
// so if you really want to see if the value has changed, you should not only check for event type `SliderEventMoved`,
// but also check if the value has changed!
#define FLAG_AUTOSNAP 0x40000000

typedef enum BitMode_ {
	UnsetBits = -1,
	SetExplicit = 0,
	SetBits = 1
} BitMode;
void __cdecl SetSliderFlags(HWND hWnd, BitMode bitMode, UINT bits);

// Adds reference to a slider which regulates the this slider's min value
void __cdecl SetSliderMin(HWND hWnd, HWND hMinSlider);

// Adds reference to a slider which regulates the this slider's max value
void __cdecl SetSliderMax(HWND hWnd, HWND hMaxSlider);

// Sets the procedures which are called by PaintSlider(). Not to be confused with the window procedure.
// If first=TRUE, then proc "1" will be set (which will be called by PaintSlider() before "2"), otherwise proc "2" will be set.
// The f_SliderProc is __cdecl and contains 3 arguments: HWND hWnd, HDC dc, SliderData* sliderData
// During the WM_QUERYOPEN event, SliderWndProc() will set the procedures to:
//    first==0 => DefPlotThumb()
//    first==1 => DefPaintBack()
// Instead of using the DLL API, you can send the custom windows message 0x4C8 which results in a call of SetSliderProc(hWnd, lParam, wParam);
void __cdecl SetSliderProc(HWND hWnd, f_SliderProc* proc, BOOL first);

// Adds an offset to the thumb in Y direction (for horizontal sliders) or X direction (for vertical sliders).
// Attention: Does not work for horizontal sliders in the new design (e.g. Photoshop 7),
// but works older PLUGIN.DLL versions, e.g. for Photoshop 3.0.
// Default values set by AllocSlider are 2 for horizontal sliders and 1 for vertical sliders.
// if offset=-1, then the slider will be put to the lower edge (BUG: This does not work for the vertical sliders!)
// Instead of using the DLL API, you can send the custom windows message 0x4CB which results in a call of SetSliderThumbOff(hWnd, wParam),
void __cdecl SetSliderThumbOff(HWND hWnd, int offset);

// Changes the size of the slider's thumb.
// Attention: Does not work for horizontal sliders in the new design (e.g. Photoshop 7),
// but works older PLUGIN.DLL versions, e.g. for Photoshop 3.0.
// Default values set by AllocSlider are {0x9, 0xA} for horizontal sliders and {0xE, 0x7} for vertical sliders.
// Instead of using the DLL API, you can send the custom windows message 0x4CA which results in a call of SetSliderthumbSize(hWnd, lParam, lParam>>16); // SIC: second argument is not &0xFFFF
void __cdecl SetSliderThumbSize(HWND hWnd, UINT width, UINT height);

// Receives the RECT (left,right,top,bottom) of the moveable thumb in its current position.
void __cdecl GetThumbRect(HWND hWnd, RECT *lprc);

#endif

Photoshop_Sliders.cpp (C++ with dynamic DLL loading)

#include "Photoshop_Sliders.h"

HMODULE hPluginDllLib = NULL;

void _LoadPluginDll() {
#ifdef _WIN64
	hPluginDllLib = LoadLibrary(TEXT("C:\\Program Files\\Adobe\\Adobe Photoshop 2024\\Plugin.dll"));
#else
	hPluginDllLib = LoadLibrary(TEXT("C:\\Program Files (x86)\\Adobe\\Photoshop 7.0\\Plugin.dll"));
#endif
	if (hPluginDllLib == NULL) hPluginDllLib = LoadLibrary(TEXT("Plugin.dll"))
}

void _UnloadPluginDll() {
	if (hPluginDllLib != NULL) {
		FreeLibrary(hPluginDllLib);
		hPluginDllLib = NULL;
	}
}

typedef int(__cdecl* f_RegisterSlider)(HINSTANCE hInstanceDll, DWORD* MessageID);
int RegisterSlider(HINSTANCE hInstanceDll, DWORD* MessageID) {
	f_RegisterSlider fRegisterSlider;

	if (!hPluginDllLib) return 0;
	fRegisterSlider = (f_RegisterSlider)(void*)GetProcAddress(hPluginDllLib, "RegisterSlider");
	if (fRegisterSlider != 0) {
		return fRegisterSlider(hInstanceDll, MessageID);
	}
	else {
		return 0;
	}
}

typedef int(__cdecl* f_UnregisterSlider)(HINSTANCE hInstanceDll);
int UnregisterSlider(HINSTANCE hInstanceDll) {
	f_UnregisterSlider fUnregisterSlider;

	if (!hPluginDllLib) return 0;
	fUnregisterSlider = (f_UnregisterSlider)(void*)GetProcAddress(hPluginDllLib, "UnregisterSlider");
	if (fUnregisterSlider != 0) {
		return fUnregisterSlider(hInstanceDll);
	}
	else {
		return 0;
	}
}

typedef void(__cdecl* f_AllocSlider)(HWND hWnd);
void __cdecl AllocSlider(HWND hWnd) {
	f_AllocSlider fAllocSlider;

	if (!hPluginDllLib) return;
	fAllocSlider = (f_AllocSlider)(void*)GetProcAddress(hPluginDllLib, "AllocSlider");
	if (fAllocSlider != 0) {
		fAllocSlider(hWnd);
	}
}

typedef void(__cdecl* f_FreeSlider)(HWND hWnd);
void __cdecl FreeSlider(HWND hWnd) {
	f_FreeSlider fFreeSlider;

	if (!hPluginDllLib) return;
	fFreeSlider = (f_FreeSlider)(void*)GetProcAddress(hPluginDllLib, "FreeSlider");
	if (fFreeSlider != 0) {
		fFreeSlider(hWnd);
	}
}

typedef int(__cdecl* f_GetSliderPos)(HWND hWnd, BOOL bPixelPosition);
int GetSliderPos(HWND hWnd, BOOL bPixelPosition) {
	f_GetSliderPos fGetSliderPos;

	if (!hPluginDllLib) return 0;
	fGetSliderPos = (f_GetSliderPos)(void*)GetProcAddress(hPluginDllLib, "GetSliderPos");
	if (fGetSliderPos != 0) {
		int res = fGetSliderPos(hWnd, bPixelPosition);
		return res;
	}
	else {
		return 0;
	}
}

typedef void(__cdecl* f_SetSliderPos)(HWND hWnd, int nPos, BOOL bRepaint);
void SetSliderPos(HWND hWnd, int nPos, BOOL bRepaint) {
	f_SetSliderPos fSetSliderPos;

	if (!hPluginDllLib) return;
	fSetSliderPos = (f_SetSliderPos)(void*)GetProcAddress(hPluginDllLib, "SetSliderPos");
	if (fSetSliderPos != 0) {
		fSetSliderPos(hWnd, nPos, bRepaint);
	}
}

typedef SliderRange(__cdecl* f_GetSliderRange)(HWND hWnd);
SliderRange GetSliderRange(HWND hWnd) {
	f_GetSliderRange fGetSliderRange;
	SliderRange res = { 0 };

	if (!hPluginDllLib) return res;
	fGetSliderRange = (f_GetSliderRange)(void*)GetProcAddress(hPluginDllLib, "GetSliderRange");
	if (fGetSliderRange != 0) {
		res = (SliderRange)fGetSliderRange(hWnd);
		return res;
	}
	else {
		return res;
	}
}

typedef void(__cdecl* f_SetSliderRange)(HWND hWnd, int nMin, int nMax);
void SetSliderRange(HWND hWnd, int nMin, int nMax) {
#if 0
	// Implementation of Photoshop 7.0:
	SliderData* data = LockSliderData(hWnd);
	data->rangeMin = nMin;
	data->rangeMax = nMax;
	UnlockSliderData(hWnd);
#else
	f_SetSliderRange fSetSliderRange;

	if (!hPluginDllLib) return;
	fSetSliderRange = (f_SetSliderRange)(void*)GetProcAddress(hPluginDllLib, "SetSliderRange");
	if (fSetSliderRange != 0) {
		fSetSliderRange(hWnd, nMin, nMax);
	}
#endif
}

typedef SliderData* (__cdecl* f_LockSliderData)(HWND hWnd);
SliderData* __cdecl LockSliderData(HWND hWnd) {
#if 0
	// Implementation of Photoshop 7.0:
	return (SliderData*)GlobalLock(GetPropA(hWnd, "PSSlData"));
#else
	f_LockSliderData fLockSliderData;
	SliderData* res = NULL;

	if (!hPluginDllLib) return res;
	fLockSliderData = (f_LockSliderData)(void*)GetProcAddress(hPluginDllLib, "LockSliderData");
	if (fLockSliderData != 0) {
		res = (SliderData*)fLockSliderData(hWnd);
		return res;
	}
	else {
		return res;
	}
#endif
}

typedef void(__cdecl* f_UnlockSliderData)(HWND hWnd);
void __cdecl UnlockSliderData(HWND hWnd) {
#if 0
	// Implementation of Photoshop 7.0:
	GlobalUnlock(GetPropA(hWnd, "PSSlData"));
#else
	f_UnlockSliderData fUnlockSliderData;

	if (!hPluginDllLib) return;
	fUnlockSliderData = (f_UnlockSliderData)(void*)GetProcAddress(hPluginDllLib, "UnlockSliderData");
	if (fUnlockSliderData != 0) {
		fUnlockSliderData(hWnd);
	}
#endif
}

typedef void(__cdecl* f_PaintSlider)(HWND hWnd, HDC dc);
void __cdecl PaintSlider(HWND hWnd, HDC dc) {
	f_PaintSlider fPaintSlider;

	if (!hPluginDllLib) return;
	fPaintSlider = (f_PaintSlider)(void*)GetProcAddress(hPluginDllLib, "PaintSlider");
	if (fPaintSlider != 0) {
		fPaintSlider(hWnd, dc);
	}
}

typedef void(__cdecl* f_SetSliderData)(HWND hWnd, void* additionalData);
void __cdecl SetSliderData(HWND hWnd, void* additionalData) {
	f_SetSliderData fSetSliderData;

	if (!hPluginDllLib) return;
	fSetSliderData = (f_SetSliderData)(void*)GetProcAddress(hPluginDllLib, "SetSliderData");
	if (fSetSliderData != 0) {
		fSetSliderData(hWnd, additionalData);
	}
}

typedef void(__cdecl* f_SetSliderFlags)(HWND hWnd, BitMode bitMode, UINT bits);
void __cdecl SetSliderFlags(HWND hWnd, BitMode bitMode, UINT bits) {
#if 0
	// Implementation of Photoshop 7.0:
	SliderData* data = LockSliderData(hWnd);
	if (bitMode == setExplicit) {
		data->flags = bits;
	}
	else if (bitMode == setBits) {
		data->flags |= bits;
	}
	else if (bitMode == unsetBits) {
		data->flags &= ~bits;
	}
	else {
		// Do nothing
	}
	UnlockSliderData(hWnd);
#else
	f_SetSliderFlags fSetSliderFlags;

	if (!hPluginDllLib) return;
	fSetSliderFlags = (f_SetSliderFlags)(void*)GetProcAddress(hPluginDllLib, "SetSliderFlags");
	if (fSetSliderFlags != 0) {
		fSetSliderFlags(hWnd, bitMode, bits);
	}
#endif
}

typedef void(__cdecl* f_SetSliderMin)(HWND hWnd, HWND hMinSlider);
void __cdecl SetSliderMin(HWND hWnd, HWND hMinSlider) {
#if 0
	// Implementation of Photoshop 7.0:
	SliderData* data = LockSliderData(hWnd);
	data->ptrSlMin = LockSliderData(hMinSlider);
	UnlockSliderData(hWnd);
	// SIC! They REALLY do that! They store a pointer to data->ptrSlMin which might be moved since the memory is allocated with GlobalAlloc(GHND) which is moveable memory!
	UnlockSliderData(hMinSlider);
#else
	f_SetSliderMin fSetSliderMin;

	if (!hPluginDllLib) return;
	fSetSliderMin = (f_SetSliderMin)(void*)GetProcAddress(hPluginDllLib, "SetSliderMin");
	if (fSetSliderMin != 0) {
		fSetSliderMin(hWnd, hMinSlider);
	}
#endif
}

typedef void(__cdecl* f_SetSliderMax)(HWND hWnd, HWND hMaxSlider);
void __cdecl SetSliderMax(HWND hWnd, HWND hMaxSlider) {
#if 0
	// Implementation of Photoshop 7.0:
	SliderData* data = LockSliderData(hWnd);
	data->ptrSlMax = LockSliderData(hMaxSlider);
	UnlockSliderData(hWnd);
	// SIC! They REALLY do that! They store a pointer to data->ptrSlMax which might be moved since the memory is allocated with GlobalAlloc(GHND) which is moveable memory!
	UnlockSliderData(hMaxSlider);
#else
	f_SetSliderMax fSetSliderMax;

	if (!hPluginDllLib) return;
	fSetSliderMax = (f_SetSliderMax)(void*)GetProcAddress(hPluginDllLib, "SetSliderMax");
	if (fSetSliderMax != 0) {
		fSetSliderMax(hWnd, hMaxSlider);
	}
#endif
}

typedef void(__cdecl* f_SetSliderProc)(HWND hWnd, f_SliderProc* proc, BOOL first);
void __cdecl SetSliderProc(HWND hWnd, f_SliderProc* proc, BOOL first) {
	f_SetSliderProc fSetSliderProc;

	if (!hPluginDllLib) return;
	fSetSliderProc = (f_SetSliderProc)(void*)GetProcAddress(hPluginDllLib, "SetSliderProc");
	if (fSetSliderProc != 0) {
		fSetSliderProc(hWnd, proc, first);
	}
}

typedef void(__cdecl* f_SetSliderThumbOff)(HWND hWnd, int offset);
void __cdecl SetSliderThumbOff(HWND hWnd, int offset) {
#if 0
	// Implementation of Photoshop 7.0:
	SliderData* data = LockSliderData(hWnd);
	if (offset == -1) {
		RECT lpRect;
		GetClientRect(hWnd, &lpRect);
		data->thumbOffset = (lpRect.bottom - (data->thumbSize.height) - (lpRect.top) - 1) & 0xFFFF;
	}
	else {
		data->thumbOffset = offset & 0xFFFF;
	}
	UnlockSliderData(hWnd);
#else
	f_SetSliderThumbOff fSetSliderThumbOff;

	if (!hPluginDllLib) return;
	fSetSliderThumbOff = (f_SetSliderThumbOff)(void*)GetProcAddress(hPluginDllLib, "SetSliderThumbOff");
	if (fSetSliderThumbOff != 0) {
		fSetSliderThumbOff(hWnd, offset);
	}
#endif
}

typedef void(__cdecl* f_SetSliderThumbSize)(HWND hWnd, UINT width, UINT height);
void __cdecl SetSliderThumbSize(HWND hWnd, UINT width, UINT height) {
#if 0
	// Implementation of Photoshop 7.0:
	SliderData* data = LockSliderData(hWnd);
	//data->thumbSize.raw = ((height & 0xFFFF) << 16) | (width & 0xFFFF);
	data->thumbSize.width = width;
	data->thumbSize.height = height;
	UnlockSliderData(hWnd);
#else
	f_SetSliderThumbSize fSetSliderThumbSize;

	if (!hPluginDllLib) return;
	fSetSliderThumbSize = (f_SetSliderThumbSize)(void*)GetProcAddress(hPluginDllLib, "SetSliderThumbSize");
	if (fSetSliderThumbSize != 0) {
		fSetSliderThumbSize(hWnd, width, height);
	}
#endif
}

typedef void(__cdecl* f_GetThumbRect)(HWND hWnd, RECT *lprc);
void __cdecl GetThumbRect(HWND hWnd, RECT *lprc) {
	f_GetThumbRect fGetThumbRect;

	if (!hPluginDllLib) return;
	fGetThumbRect = (f_GetThumbRect)(void*)GetProcAddress(hPluginDllLib, "GetThumbRect");
	if (fGetThumbRect != 0) {
		fGetThumbRect(hWnd, lprc);
	}
}

Some interesting internal methods (you should not call them directly)

// The window procedure, set to WndClass.lpfnWndProc by RegisterSlider().
// (I have no idea why such methods are exported by the DLL...)
typedef LRESULT(__cdecl* f_SliderWndProc)(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
LRESULT CALLBACK SliderWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
#if 0
	// Implementation of Photoshop 7.0:
	if (uMsg == WM_SIZE) {
		BufferDraw(hWnd, 1);
	} else if (uMsg == WM_QUIT) {
		FreeSlider(hWnd);
	} else if (uMsg == WM_QUERYOPEN) {
		AllocSlider(hWnd);
		SetSliderProc(hWnd, &DefPaintBack, TRUE);
		SetSliderProc(hWnd, &DefPlotThumb, FALSE);
	} else if (uMsg == WM_ERASEBKGND) {
		if (gMouseCaptured) return (LRESULT)0;
	} else if (uMsg == WM_LBUTTONDOWN) {
		DragThumb(hWnd);
	} else if (uMsg == 0x4C8) {
		SetSliderProc(hWnd, lParam, wParam);
	} else if (uMsg == 0x4C9) {
		SetSliderData(hWnd, lParam);
	} else if (uMsg == 0x4CA) {
		SetSliderThumbSize(hWnd, lParam, lParam>>16); // SIC: second argument is not &0xFFFF
	} else if (uMsg == 0x4CB) {
		SetSliderThumbOff(hWnd, wParam),
	} else if (uMsg == 0x4CC) {
		SetSliderPos(hWnd, wParam, 1);
	} else if (uMsg == 0x4CD) {
		return GetSliderPos(hWnd, wParam);
	} else if (uMsg == 0x4CE) {
		return GetSliderRange(hWnd);
	} else if (uMsg == 0x4CF) {
		SetSliderRange(hWnd, lParam&0xFFFF, lParam>>16);
	}
	return DefWindowProc(hWnd, uMsg, wParam, lParam);
#else
	f_SliderWndProc fSliderWndProc;
	LRESULT res = 0;
	if (!hPluginDllLib) return res;
	fSliderWndProc = (f_SliderWndProc)(void*)GetProcAddress(hPluginDllLib, "SliderWndProc");
	if (fSliderWndProc != 0) {
		res = (LRESULT)fSliderWndProc(hWnd, uMsg, wParam, lParam);
		return res;
	}
	else {
		return res;
	}

#endif
}

// Internally called
// If BOOL bLogical==0 then use map_to_physical() internally, otherwise use map_to_logical() internally.
//    map_to_logical (int param_1,int param_2,int param_3,int param_4) = ((param_4 - param_3) * param_1 + param_2 / 2) / param_2 + param_3;
//    map_to_physical(int param_1,int param_2,int param_3,int param_4) = ((param_4 - param_3) / 2 + (param_1 - param_3) * param_2) / (param_4 - param_3);
// Flag "0x20000000" (negated bit #29) will be added as UNUSED fifth argument to map_to_logical() and map_to_physical().
// This "dead" flag was seen in PS3 and PS7, but not PS2024. So it seems to have been dead since its first release in PS3.
int/*?*/ __cdecl TranslatePos(HWND hWnd, int unk1, BOOL bLogical);
typedef int(__cdecl* f_TranslatePos)(HWND hWnd, int param_unk1, BOOL bLogical);
int __cdecl TranslatePos(HWND hWnd, int param_unk1, BOOL bLogical) {
#if 0
	// Disassembled...
	RECT rect;
	int iThumbSize, iScaleMinusThumbSize;
	SliderData* data = LockSliderData(hWnd);
	GetClientRect(hWnd, &rect);
	if (data->verticalSlider) {
		iThumbSize = data->thumbSize.height;
		iScaleMinusThumbSize = (rect.bottom - rect.top) - iThumbSize;
	}
	else {
		iThumbSize = data->thumbSize.width;
		iScaleMinusThumbSize = (rect.right - rect.left) - iThumbSize;
	}
	if (bLogical) {
		int iVar4 = param_unk1 - iThumbSize / 2;
		if (iVar4 < 0) {
			iVar4 = 0;
		}
		if (iVar4 > iScaleMinusThumbSize) {
			iVar4 = iScaleMinusThumbSize;
		}
		UnlockSliderData(hWnd);
		//return map_to_logical(iVar4, iScaleMinusThumbSize, data->rangeMin, data->rangeMax);
		return ((data->rangeMax - data->rangeMin) * iVar4 + iScaleMinusThumbSize / 2) / iScaleMinusThumbSize + data->rangeMin;
	}
	else {
		if (param_unk1 < data->rangeMin) {
			param_unk1 = data->rangeMin;
		}
		if (param_unk1 > data->rangeMax) {
			param_unk1 = data->rangeMax;
		}
		UnlockSliderData(hWnd);
		//return map_to_physical(param_unk1, iScaleMinusThumbSize, data->rangeMin, data->rangeMax) + iThumbSize / 2;
		return ((data->rangeMax - data->rangeMin) / 2 + (param_unk1 - data->rangeMin) * iScaleMinusThumbSize) / (data->rangeMax - data->rangeMin);
	}
#else
	f_TranslatePos fTranslatePos;
	int res = 0;
	if (!hPluginDllLib) return res;
	fTranslatePos = (f_TranslatePos)(void*)GetProcAddress(hPluginDllLib, "TranslatePos");
	if (fTranslatePos != 0) {
		res = (int)fTranslatePos(hWnd, param_unk1, bLogical);
		return res;
	}
	else {
		return res;
	}
#endif
}

Message "PSSlCmd" (get the MessageID from RegisterSlider)

Received wParam = ID of the control

Received lParam = lower 16 bits (SLIDER_POS(lParam)) is the position, (SLIDER_EVENT(lParam)) 16 bits is the kind of event:

0x7FFB (SliderEventMoved) = Everytime the mouse moves and the thumb is dragged, or if the the user clicked on the scale for an instant jump (and once the mouse button is released, 0xFFFC will be sent)
0x7FFC (SliderEventReleased) = When mouse button is released (also if thumb was just clicked, not dragged)
0x7FFD (SliderEventIdle) = When the mouse is idle while the thumb is clicked and hold, after a short initial pause, it will fire in a fast interval
0x7FFE (SliderEventIdleOnce) = When the mouse is idle while the thumb is clicked and hold, but will only fire once after a short initial pause