Old 24th August 2022, 22:07   #1
Ingvar
Junior Member
 
Join Date: Aug 2022
Posts: 20
Skin support for plugin window controls

Hello! I am writing my own plugin. It creates own window. The resource dialog fits nicely into the new window. But here is the problem - all controls do not have a skin support:

Click image for larger version

Name:	waa.jpg
Views:	96
Size:	12.3 KB
ID:	55012

How to fix it?
Ingvar is offline   Reply With Quote
Old 25th August 2022, 15:24   #2
thinktink
Forum King
 
thinktink's Avatar
 
Join Date: May 2009
Location: No longer on the streets of Kings County, CA.
Posts: 3,189
I'm assuming you've already checked the source code for the example embedded window plugin here: http://forums.winamp.com/showthread.php?t=322114

If you can, post your source code in a zip or 7z archive so I can see if I can find any obvious errors.
thinktink is online now   Reply With Quote
Old 26th August 2022, 02:12   #3
Ingvar
Junior Member
 
Join Date: Aug 2022
Posts: 20
Quote:
Originally Posted by thinktink View Post
I'm assuming you've already checked the source code for the example embedded window plugin here
All given links in this thread to the webpage with the example window are no longer available, i.e. article deleted.

But all I could find was the need to handle messages of embedded dialog proc like this:

code:
case WM_CTLCOLORLISTBOX:
case WM_CTLCOLORDLG:
case WM_CTLCOLORBTN:
case WM_CTLCOLORSTATIC:
case WM_CTLCOLOREDIT:
case WM_DRAWITEM:
{
return WADlg_handleDialogMsgs(hwnd, msg, wParam, lParam);
}


Now it works correct. Is everything right here?



Another one offtopic question: I added the plugin menu item to Winamp main menu using InsertMenuItem() function with text and shortcut:
code:
wchar_t menu_caption[] = L"My plugin name\tAlt+B";


By handling WM_COMMAND I process menu click. And it works. But when I press Alt+B shortcut associated with menu item - nothing happens.

How to fix this?
Ingvar is offline   Reply With Quote
Old 26th August 2022, 20:22   #4
thinktink
Forum King
 
thinktink's Avatar
 
Join Date: May 2009
Location: No longer on the streets of Kings County, CA.
Posts: 3,189
I could have SWORN I downloaded that example plugin a long time ago but I still can't find it.

However, you can use the following for an example:
http://forums.winamp.com/showthread....83#post3215083
It should have everything you need to learn standard skinning support. It also contains an example for shortcut handling.

Unfortunately, there is no native skinning support for radio buttons and checkboxes.

Your edit box doesn't look right. Before going on a tare, check the example I provided for that.
thinktink is online now   Reply With Quote
Old 27th August 2022, 01:28   #5
Ingvar
Junior Member
 
Join Date: Aug 2022
Posts: 20
thinktink, thanks for example!

I have added this code:
code:
api_application *WASABI_API_APP;
api_service *WASABI_API_SVC;

template <class api_T>
void ServiceBuild(api_T *&api_t, GUID factoryGUID_t)
{
if(WASABI_API_SVC)
{
waServiceFactory *factory = WASABI_API_SVC->service_getServiceByGuid(factoryGUID_t);

if(factory)
{
api_t = (api_T*)factory->getInterface();
}
}
}



on init():
code:
WADlg_init(plugin.hwndParent);

WASABI_API_SVC = (api_service*)SendMessage(plugin.hwndParent, WM_WA_IPC, 0, IPC_GET_API_SERVICE);

if(WASABI_API_SVC != NULL)
{
ServiceBuild(WASABI_API_APP, applicationApiServiceGuid);
}



except WASABI_API_CREATEDIALOGW I still use: CreateDialogParam(...

code:
ACCEL accel = {FVIRTKEY | FALT, 'A', MY_PLUGINMENU_ID};
HACCEL hAccel = CreateAcceleratorTable(&accel, 1);
WASABI_API_APP->app_addAccelerators(embedWnd, &hAccel, 1, TRANSLATE_MODE_NORMAL);



code:
DlgProc:
case WM_COMMAND:
{
if(LOWORD(wParam) == MY_PLUGINMENU_ID)
{
MessageBox(hwnd, L"This is hotkey!", L"", MB_OK);
}

break;
}



But when I press Alt+A nothing happens. Hotkey not work. Maybe I something missed?
Ingvar is offline   Reply With Quote
Old 27th August 2022, 17:33   #6
Ingvar
Junior Member
 
Join Date: Aug 2022
Posts: 20
Another one question: thinktink, your project compiled succesfully, but when I try to compile my project compiler throws error:
Quote:
error LNK2001: unresolved external symbol "class api_language * languageManager" (?languageManager@@3PAVapi_language@@A)
I add paths to Winamp SDK in PROJECT->my_project properties->VC++ Directories->Include Directories:
Quote:
D:\Winamp_SDK;D:\Winamp_SDK\Wasabi;D:\Winamp_SDK\Agave;$(IncludePath)
But compiler still error LNK2001: unresolved external symbol "class api_language * languageManager"
Ingvar is offline   Reply With Quote
Old 27th August 2022, 17:57   #7
thinktink
Forum King
 
thinktink's Avatar
 
Join Date: May 2009
Location: No longer on the streets of Kings County, CA.
Posts: 3,189
Quote:
Originally Posted by Ingvar View Post
thinktink, thanks for example!

I have added this code:
code:
api_application *WASABI_API_APP;
api_service *WASABI_API_SVC;

template <class api_T>
void ServiceBuild(api_T *&api_t, GUID factoryGUID_t)
{
if(WASABI_API_SVC)
{
waServiceFactory *factory = WASABI_API_SVC->service_getServiceByGuid(factoryGUID_t);

if(factory)
{
api_t = (api_T*)factory->getInterface();
}
}
}



on init():
code:
WADlg_init(plugin.hwndParent);

WASABI_API_SVC = (api_service*)SendMessage(plugin.hwndParent, WM_WA_IPC, 0, IPC_GET_API_SERVICE);

if(WASABI_API_SVC != NULL)
{
ServiceBuild(WASABI_API_APP, applicationApiServiceGuid);
}



except WASABI_API_CREATEDIALOGW I still use: CreateDialogParam(...

code:
ACCEL accel = {FVIRTKEY | FALT, 'A', MY_PLUGINMENU_ID};
HACCEL hAccel = CreateAcceleratorTable(&accel, 1);
WASABI_API_APP->app_addAccelerators(embedWnd, &hAccel, 1, TRANSLATE_MODE_NORMAL);



code:
DlgProc:
case WM_COMMAND:
{
if(LOWORD(wParam) == MY_PLUGINMENU_ID)
{
MessageBox(hwnd, L"This is hotkey!", L"", MB_OK);
}

break;
}



But when I press Alt+A nothing happens. Hotkey not work. Maybe I something missed?
How have you generated/set/defined "MY_PLUGINMENU_ID"?

I do it with:
code:
MY_PLUGINMENU_ID=(UINT)::SendMessage(plugin.hwndParent,WM_WA_IPC,(WPARAM)0,IPC_REGISTER_LOWORD_COMMAND);
thinktink is online now   Reply With Quote
Old 27th August 2022, 18:07   #8
thinktink
Forum King
 
thinktink's Avatar
 
Join Date: May 2009
Location: No longer on the streets of Kings County, CA.
Posts: 3,189
Quote:
Originally Posted by Ingvar View Post
...

code:
DlgProc:
case WM_COMMAND:
{
if(LOWORD(wParam) == MY_PLUGINMENU_ID)
{
MessageBox(hwnd, L"This is hotkey!", L"", MB_OK);
}

break;
}



But when I press Alt+A nothing happens. Hotkey not work. Maybe I something missed?
Have you subclassed the Winamp main HWND and checking WM_COMMAND/WM_SYSCOMMAND in there or are you checking inside your own embed wnd's DlgProc instead? If you can't subclass Winamp's main HWND then you can also check inside a Windows Hook (see SetWindowsHookEx in the MSDN for usage).
thinktink is online now   Reply With Quote
Old 27th August 2022, 20:18   #9
thinktink
Forum King
 
thinktink's Avatar
 
Join Date: May 2009
Location: No longer on the streets of Kings County, CA.
Posts: 3,189
Quote:
Originally Posted by Ingvar View Post
Another one question: thinktink, your project compiled succesfully, but when I try to compile my project compiler throws error:

I add paths to Winamp SDK in PROJECT->my_project properties->VC++ Directories->Include Directories:

But compiler still error LNK2001: unresolved external symbol "class api_language * languageManager"
I'm not sure about your version of the compiler but I'm using the free Microsoft Visual C++ 2010 Express to build gen_classicart. If you're doing the same:

Open "gen_yourplugin" Property Pages

Select: All Configurations

Go to: Configuration Properties -> C/C++ -> General

Inspect "Additional Include Directories" and make sure the subfolders in the Winamp SDK folder labeled "Wasabi", "Agave", and "Winamp" are being included.

Attached Thumbnails
Click image for larger version

Name:	Additional Include Directories.PNG
Views:	318
Size:	9.1 KB
ID:	55027  
thinktink is online now   Reply With Quote
Old 28th August 2022, 00:09   #10
Ingvar
Junior Member
 
Join Date: Aug 2022
Posts: 20
Quote:
Originally Posted by thinktink View Post
How have you generated/set/defined "MY_PLUGINMENU_ID"?
I didn't generate value for MY_PLUGINMENU_ID. Just assign a value:
code:
UINT MY_PLUGINMENU_ID = 0xa2bc;


Quote:
Originally Posted by Ingvar View Post
but when I try to compile my project compiler throws error: unresolved external symbol "class api_language * languageManager"
It was my mistake . When I was writing the code I wrote accidentally.
code:
api_language *WASAPI_API_LNG;

instead of:
code:
api_language *WASABI_API_LNG;

Quote:
Originally Posted by Ingvar View Post
But when I press Alt+A nothing happens
I also made a mistake here . And I found it while reading your project. I wrote:
code:
WASABI_API_APP->app_addAccelerators(dialogWnd, &hAccel, 1, TRANSLATE_MODE_NORMAL);

instead of:
code:
WASABI_API_APP->app_addAccelerators(dialogWnd, &hAccel, 1, TRANSLATE_MODE_GLOBAL);

But I found a bug in your code too . Look at quit() function:
code:
// restores the original playlist window proc now that we are closing and if the window was subclassed
HWND pe_wnd = (HWND)SendMessage(plugin.hwndParent,WM_WA_IPC,IPC_GETWND_PE,IPC_GETWND);
if(GetWindowLongPtr(pe_wnd,GWLP_WNDPROC) == (LONG_PTR)SubclassPlaylistProc){
SetWindowLongPtr(pe_wnd,GWLP_WNDPROC,(LONG_PTR)oldPlaylistWndProc);
}


At this moment, the GetWindowLongPtr() function will return 0x00 because the parent window no longer exists. You can verify it using debugger.
Therefore, this code should be moved to the parent window's dialog proc into the WM_DESTROY handler.

But now it's time to return to the main question of the topic.
I opened your "gen_classicart" project and edited the resource dialog: I placed some controls - button, text label and a edit control. Compile and run it in Winamp:



It looks like skin support isn't working for controls. I didn't modify source code except GEN_INIT_FAILURE replace with 1 (I didn't find a definition). So how to theme the controls?
Ingvar is offline   Reply With Quote
Old 29th August 2022, 14:18   #11
thinktink
Forum King
 
thinktink's Avatar
 
Join Date: May 2009
Location: No longer on the streets of Kings County, CA.
Posts: 3,189
Quote:
Originally Posted by Ingvar View Post
I didn't generate value for MY_PLUGINMENU_ID. Just assign a value:
code:
UINT MY_PLUGINMENU_ID = 0xa2bc;...
Go ahead and do it the way I showed, it will help prevent future conflicts with other plugins and is the SDK way to do it.

Quote:
Originally Posted by Ingvar View Post
...


But I found a bug in your code too . Look at quit() function:
code:
// restores the original playlist window proc now that we are closing and if the window was subclassed
HWND pe_wnd = (HWND)SendMessage(plugin.hwndParent,WM_WA_IPC,IPC_GETWND_PE,IPC_GETWND);
if(GetWindowLongPtr(pe_wnd,GWLP_WNDPROC) == (LONG_PTR)SubclassPlaylistProc){
SetWindowLongPtr(pe_wnd,GWLP_WNDPROC,(LONG_PTR)oldPlaylistWndProc);
}


At this moment, the GetWindowLongPtr() function will return 0x00 because the parent window no longer exists. You can verify it using debugger.
Therefore, this code should be moved to the parent window's dialog proc into the WM_DESTROY handler.
That is actually a good thing, it means that the window is being destroyed BEFORE your plugin is unloaded from memory.
Trying to "unsubclass" a shared window is problematic at best as not all plugins are guaranteed to be loaded and unloaded in the correct order to prevent subclass procedure chain breaks, which is very bad. If your subclass proceedure is unloaded (by dint of your plugin being unloaded) before the window it's connected to is destroyed it will cause Access Violations when the (now non-existent) procedure is called.


Quote:
Originally Posted by Ingvar View Post

But now it's time to return to the main question of the topic.
I opened your "gen_classicart" project and edited the resource dialog: I placed some controls - button, text label and a edit control. Compile and run it in Winamp:



It looks like skin support isn't working for controls. I didn't modify source code except GEN_INIT_FAILURE replace with 1 (I didn't find a definition). So how to theme the controls?
Since that window never had standard controls to skin, the original developer never put in the code to skin any. Go ahead and add the handler inside "art_dlgproc" switch/case statements, between the WM_DESTROY and WM_PAINT case statements seems like a good place.
PHP Code:
case WM_CTLCOLORLISTBOX:
case 
WM_CTLCOLORDLG:
case 
WM_CTLCOLORBTN:
case 
WM_CTLCOLORSTATIC:
case 
WM_CTLCOLOREDIT:
case 
WM_DRAWITEM:
{
return 
WADlg_handleDialogMsgs(hwndmsgwParamlParam);



PHP Code:
#define GEN_INIT_FAILURE 1
#define GEN_INIT_SUCCESS 0 
Those are defined in GEN.H in the Winamp SDK
thinktink is online now   Reply With Quote
Old 29th August 2022, 15:54   #12
thinktink
Forum King
 
thinktink's Avatar
 
Join Date: May 2009
Location: No longer on the streets of Kings County, CA.
Posts: 3,189
Found it!

I finally found the example package.

Attached.
Attached Files
File Type: zip Nullsoft_Embedded_Window_Example_v1_1.zip (144.7 KB, 105 views)
thinktink is online now   Reply With Quote
Old 31st August 2022, 01:16   #13
Ingvar
Junior Member
 
Join Date: Aug 2022
Posts: 20
Quote:
Originally Posted by thinktink View Post
I finally found the example package
Thanks!
Quote:
Originally Posted by thinktink View Post
That is actually a good thing, it means that the window is being destroyed BEFORE your plugin is unloaded from memory.
I think you understood me correctly. Anyway it would be correct to move unsubclass code to the parent window's dialog proc at the WM_DESTROY.
Quote:
Originally Posted by thinktink View Post
Since that window never had standard controls to skin, the original developer never put in the code to skin any. Go ahead and add the handler inside "art_dlgproc" switch/case statements
Thanks! Now it looks right:



Quote:
Originally Posted by thinktink View Post
Those are defined in GEN.H in the Winamp SDK
It's weird but I downloaded Winamp SDK 5.5 from here https://download.nullsoft.com/winamp...WA5.55_SDK.exe and Winamp/gen.h file contains only #define GEN_INIT_SUCCESS 0.

While looking through your code and using the debugger, I found another one bug. Looks like it's a winamp bug.
Look at this code:

code:
else if(msg == WM_WA_IPC)
{
if(lParam == IPC_CB_MISC && (wParam == IPC_CB_MISC_TITLE || wParam == IPC_CB_MISC_TITLE_RATING))
{

//THIS BLOCK RUNS 4 TIMES !!!

// art change
PostMessage(myWndChild,WM_USER,0,0);
}



As I marked, this block runs 4 times when track changing or when you press ffwd/rwd. I think you need to handle another notification to monitor the track change.

Offtopic. In Visual Studio 2012 I set configuration to "Release" and compiled my plugin dll. But Winamp loads it only on my PC.
I sent it to another PC and also tried it on a virtual system using the latest Winamp, but in these cases Winamp doesn't load my plugin.
In the "Preferences" window I see "NOT LOADED" message. And log file \AppData\Roaming\Winamp\winamp.log contains error:
Quote:
[5.9.0.9999] [error] Error when loading the plugin 'gen_wa_plugin.dll'! Error code : 126!
For example, gen_classicart.dll works fine.
What other project settings do I need to set to compile my plugin to distribute it on other PCs?
Ingvar is offline   Reply With Quote
Old 31st August 2022, 21:17   #14
thinktink
Forum King
 
thinktink's Avatar
 
Join Date: May 2009
Location: No longer on the streets of Kings County, CA.
Posts: 3,189
Quote:
Originally Posted by Ingvar View Post
Thanks!
You're welcome.



Quote:
Originally Posted by Ingvar View Post
I think you understood me correctly. Anyway it would be correct to move unsubclass code to the parent window's dialog proc at the WM_DESTROY.
Nope, as I said before, Winamp is not guaranteed to unload other plugins that also subclass the Winamp windows in the correct order. In this case, at least WM_NCDESTROY (if not more messages) will be called after your attempt to unsubclass after the call to WM_DESTROY completes, which can potentially break the subclass chain. If it does then it will cause an access violation if the plugin's subclass proc become unavailable. You might not even see the AV error unless you put Winamp under a debugger. To be honest, the unsubclassing code should just be outright deleted. However, I'm not the original developer of the plugin so I can only guess what the original developer intended.


Quote:
Originally Posted by Ingvar View Post
Thanks! Now it looks right:

It's definitely an improvement but not entirely correct, it looks like there's a white border around what looks like edit controls, which is not part of the selected skin. The checkboxes also aren't completely skinned, but as I said before, there's currently no native support for skinning checkboxes or radio buttons.


Quote:
Originally Posted by Ingvar View Post
It's weird but I downloaded Winamp SDK 5.5 from here https://download.nullsoft.com/winamp...WA5.55_SDK.exe and Winamp/gen.h file contains only #define GEN_INIT_SUCCESS 0.
Ok, that's odd. I may have put in the other #define into the SDK source myself and forgot that I did so. If you don't want to modify the SDK headers then just add...
PHP Code:
#ifndef GEN_INIT_FAILURE
#define GEN_INIT_FAILURE 1
#endif //GEN_INIT_FAILURE 
...right after the GEN.H include. This way will prevent any warning in the future about duplicate definitions if a new version of the SDK is published with new/updated #define(s).


Quote:
Originally Posted by Ingvar View Post
While looking through your code and using the debugger, I found another one bug. Looks like it's a winamp bug.
Look at this code:

code:
else if(msg == WM_WA_IPC)
{
if(lParam == IPC_CB_MISC && (wParam == IPC_CB_MISC_TITLE || wParam == IPC_CB_MISC_TITLE_RATING))
{

//THIS BLOCK RUNS 4 TIMES !!!

// art change
PostMessage(myWndChild,WM_USER,0,0);
}



As I marked, this block runs 4 times when track changing or when you press ffwd/rwd. I think you need to handle another notification to monitor the track change.
I'm not the original developer of the plugin so I can only assume or guess the original intent. It may very well be that those messages are all included to catch all instances of changes for peculiar or specific situations and multiple calls are simply an unfortunate result of the requirements during normal operations.


Quote:
Originally Posted by Ingvar View Post
Offtopic. In Visual Studio 2012 I set configuration to "Release" and compiled my plugin dll. But Winamp loads it only on my PC.
I sent it to another PC and also tried it on a virtual system using the latest Winamp, but in these cases Winamp doesn't load my plugin.
In the "Preferences" window I see "NOT LOADED" message. And log file \AppData\Roaming\Winamp\winamp.log contains error:

For example, gen_classicart.dll works fine.
What other project settings do I need to set to compile my plugin to distribute it on other PCs?
I don't remember the name of the settings but what you're describing sounds like a missing dependency on the computer where the plugin is not loading. Google would be a better resource to figure out what's missing than me. I don't use Visual Studio on a regular basis, only when I absolutely have to, so I'm not uber familiar with specifics or details.
thinktink is online now   Reply With Quote
Old 1st September 2022, 12:21   #15
Ingvar
Junior Member
 
Join Date: Aug 2022
Posts: 20
Quote:
Originally Posted by thinktink View Post
Winamp is not guaranteed to unload other plugins that also subclass the Winamp windows in the correct order.
Do you mean that if WM_DESTROY event occurs and we try to assign a window procedure that holds in memory of already unloaded at this time plugin, then an AV error will occurs?
Quote:
Originally Posted by thinktink View Post
The checkboxes also aren't completely skinned
On my last screenshot I overridden its WM_PAINT handler and did ownerdraw checkbox painting. Should it look different? How?
Quote:
Originally Posted by thinktink View Post
there's currently no native support for skinning checkboxes or radio buttons
It looks like there is skinning support for push buttons and scrollbar only.
I used code to get skin HBITMAP and save it to file:
code:
SendMessage(plugin.hwndParent, WM_WA_IPC, 0, IPC_GET_GENSKINBITMAP);

And skin HBITMAP contains this:


As we can see, there glyphs for push-button and scrollbar are only.

By the way, where is this image stored? In what file? I looked through all the graphic and resources files in the Winamp folder but didn't find these glyphs.

Quote:
Originally Posted by thinktink View Post
it looks like there's a white border around what looks like edit controls, which is not part of the selected skin
Ok, how to fix it to assign edit control skin support? How is it done in Jump to File plugin, for example?



Here we can see specific themed borders at the bottom and right side of EDIT control. I tried to change the styles of the control, but I could not get such borders.

Is the source code of Jump to File plugin available? I can't find it. I would be able to see the implementation of the edit control.
Ingvar is offline   Reply With Quote
Old 1st September 2022, 19:07   #16
thinktink
Forum King
 
thinktink's Avatar
 
Join Date: May 2009
Location: No longer on the streets of Kings County, CA.
Posts: 3,189
Quote:
Originally Posted by Ingvar View Post
Do you mean that if WM_DESTROY event occurs and we try to assign a window procedure that holds in memory of already unloaded at this time plugin, then an AV error will occurs?
Potentially yes, it greatly depends on the order which Winamp unloads the various types of plugins during Winamp's shutdown/close. I've seen it before with my plugins.

Quote:
Originally Posted by Ingvar View Post
On my last screenshot I overridden its WM_PAINT handler and did ownerdraw checkbox painting. Should it look different? How?
I would think so, yes. How you do it is up to you since you would have to code it yourself like I had to for my plugins. You can also try just not using checkboxes and use toggle buttons or even combo boxes (which requires ML skinning support currently) that have native support. However, if you do it yourself, try to make them look like mine: http://forums.winamp.com/showpost.ph...1&postcount=63



Quote:
Originally Posted by Ingvar View Post
It looks like there is skinning support for push buttons and scrollbar only.
I used code to get skin HBITMAP and save it to file:
code:
SendMessage(plugin.hwndParent, WM_WA_IPC, 0, IPC_GET_GENSKINBITMAP);

And skin HBITMAP contains this:


As we can see, there glyphs for push-button and scrollbar are only.
Yup.


Quote:
Originally Posted by Ingvar View Post
By the way, where is this image stored? In what file? I looked through all the graphic and resources files in the Winamp folder but didn't find these glyphs.
For modern skins there is no image store, I believe it's generated internally by Winamp based on the current color scheme of the selected modern skin, but that's a guess. For classic skins they exist inside the classic skin archive (or folder if it's not in an archive), I forgot the name of the file.


Quote:
Originally Posted by Ingvar View Post
Ok, how to fix it to assign edit control skin support? How is it done in Jump to File plugin, for example?



Here we can see specific themed borders at the bottom and right side of EDIT control. I tried to change the styles of the control, but I could not get such borders.

Is the source code of Jump to File plugin available? I can't find it. I would be able to see the implementation of the edit control.
As far as I know JTFE was never open source so the code is not available. It could be an incompatible resource style set on the edit control but I've never seen that before like that. I would suggest ripping the dialog resource out of JTFE and comparing the Style and Extended Style flags of the edit control itself for clues.
thinktink is online now   Reply With Quote
Old 2nd September 2022, 19:43   #17
Ingvar
Junior Member
 
Join Date: Aug 2022
Posts: 20
Quote:
Originally Posted by thinktink View Post
You can also try just not using checkboxes
Why?
Quote:
Originally Posted by thinktink View Post
use toggle buttons
What is the toggle buttons?
Quote:
Originally Posted by thinktink View Post
As far as I know JTFE was never open source so the code is not available. It could be an incompatible resource style set on the edit control
I have looked at the resources in gen_jumpex.dll file. But there is no such dialog. It looks like it is created dynamically using CreateWindow(). But Spy++ shows these styles:
Quote:
Class Name: Edit

WS_CHILDWINDOW
WS_VISIBLE
WS_TABSTOP
ES_LEFT
ES_AUTHOHSCROLL

WS_EX_LEFT
WS_EX_LTRREADING
WS_EX_RIGHTSCROLLBAR
WS_EX_NOPARENTNOTIFY
I created an edit control with the same styles:
code:
CreateWindowEx(WS_EX_LEFT | WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR | WS_EX_NOPARENTNOTIFY, L"EDIT", L"Edit control", WS_CHILDWINDOW | WS_VISIBLE | WS_TABSTOP | ES_LEFT | ES_AUTOHSCROLL, 20, 20, 75, 28, hwnd, NULL, plugin.hDllInstance, NULL);

But it doesn't look like it in Jump to File window:



As you can see there is no bottom and right side borders.

I also noticed that button with BS_OWNERDRAW style flickers when switching between the plugin window and the main window and back.
I also have set the WS_CLIPSIBLINGS and WS_CLIPCHILDREN styles for the button's parent window (i.e. for the dialog).

But with this:
code:
case WM_DRAWITEM:
{
DRAWITEMSTRUCT *di = (DRAWITEMSTRUCT *)lParam;
FillRect(di->hDC, &di->rcItem, blue_brush);
return true;
}



or with this:
code:
case WM_DRAWITEM:
{
return WADlg_handleDialogMsgs(hwnd, msg, wParam, lParam);
}



button flickers:



However, in the JTF plugin window, the buttons do not blink! However, despite the fact that JTF's buttons have BS_OWNERDRAW style, their parent window (dialog) does not receive WM_DRAWITEM message (I see it in Spy++). But why??
According to documentation:
Quote:
for BS_OWNERDRAW style: The owner window receives a WM_DRAWITEM message when a visual aspect of the button has changed
Nonetheless, how to get rid of the flickering of the ownerdraw buttons?
Ingvar is offline   Reply With Quote
Old 5th September 2022, 21:11   #18
Ingvar
Junior Member
 
Join Date: Aug 2022
Posts: 20
Ok, so how do I get or calculate the text color for an inactive button?

For example, for a Bento skin the inactive text color should be: 91, 94, 95:
And for Winamp Modern Skin - 147, 149, 155

I checked all colors that WADlg_getColor() function returns. There is no such colors! Also I checked the contents of the skin bitmap (IPC_GET_GENSKINBITMAP). There is no such colors also.

It's like the text color for an inactive button is calculated by some formula.

I found the formula inside wa_dlg.h file:
PHP Code:
fg wadlg_colors[WADLG_WNDFG];
bg wadlg_colors[WADLG_WNDBG];
colour RGB((GetRValue(fg)+GetRValue(bg))/2, (GetGValue(fg)+GetGValue(bg))/2, (GetBValue(fg)+GetBValue(bg))/2); 
But this calculation gives wrong color. For example, for Bento:

fg = 210, 210, 210
bg = 51, 55, 56
colour = (210+51)/2, (210+55)/2, (210+56)/2 = 130, 132, 133

When DrawText() with this color, then we will see:



Similarly for Winamp Modern:

fg = 255, 255, 255
bg = 127, 135, 149
colour = (255+127)/2, (255+135)/2, (255+149)/2 = 191, 195, 202

When DrawText() with this color, then we will see:



As you can see, this is an incorrect calculation formula.

For example in JTF plugin inactive buttons has the correct text color.


So how do you calculate the correct color values for inactive text?
Ingvar is offline   Reply With Quote
Old 6th September 2022, 15:07   #19
thinktink
Forum King
 
thinktink's Avatar
 
Join Date: May 2009
Location: No longer on the streets of Kings County, CA.
Posts: 3,189
I'm working on an unauthorized update to the example plugin originally created by DrO with skinned controls and menus. It should answer a number of questions. Just need a little time.
thinktink is online now   Reply With Quote
Old 7th September 2022, 06:10   #20
thinktink
Forum King
 
thinktink's Avatar
 
Join Date: May 2009
Location: No longer on the streets of Kings County, CA.
Posts: 3,189


Hope this helps...
Attached Thumbnails
Click image for larger version

Name:	GenExample.png
Views:	270
Size:	6.4 KB
ID:	55053  
Attached Files
File Type: zip Nullsoft_Embedded_Window_Example_(Unauthorized)_v1_2.zip (156.0 KB, 103 views)
thinktink is online now   Reply With Quote
Old 10th September 2022, 01:46   #21
Ingvar
Junior Member
 
Join Date: Aug 2022
Posts: 20
Despite some errors in your code, the principle of skinning the controls is clear.

In short, in order to skin the controls, the developer needs to either draw them completely (owner drawing) or use a wrapper functions from wa_dlg.h, or request the API of the media library plugin to perform the skinning of the controls.

I also noticed that when using Media library API you must also use the WADlg_DrawChildWindowBorders() function for drawing borders, because Media library API does not draw it. It's strange that drawing borders is not part of skinning support of the Media library API.

To perform skinning of the edit control, I tried to use the media library API:

PHP Code:
//on WM_INITDIALOG
MLSKINWINDOW mlsw = {0};
mlsw.hwndToSkin GetDlgItem(hwndIDC_EDIT1);
mlsw.skinType SKINNEDWND_TYPE_EDIT;
mlsw.style SWS_USESKINCOLORS SWS_USESKINCURSORS SWS_USESKINFONT;
MLSkinWindow(ML_hWnd, &mlsw);

//on WM_PAINT draw borders (because ML API doesn't support it)
WADlg_DrawChildWindowBorders(...) 
And it works well except that it keeps using the default font and not the skin font.
As you can see the required bit SWS_USESKINFONT is set.



The only way to set the correct font for an edit control is to create a font and set it with WM_SETFONT for Edit control and not set SWS_USESKINFONT bit in mlsw.style.

I just don't understand why SWS_USESKINFONT bit doesn't work.
Ingvar is offline   Reply With Quote
Old 11th September 2022, 00:24   #22
thinktink
Forum King
 
thinktink's Avatar
 
Join Date: May 2009
Location: No longer on the streets of Kings County, CA.
Posts: 3,189
Quote:
Originally Posted by Ingvar View Post
Despite some errors in your code...
If you can, please mark the errors so that I can correct them.
thinktink is online now   Reply With Quote
Old 16th September 2022, 16:27   #23
Ingvar
Junior Member
 
Join Date: Aug 2022
Posts: 20
Quote:
Originally Posted by thinktink View Post
please mark the errors
I tested your plugin (embedded window) and found that WADlg_DrawChildWindowBorders() function draws wrong borders for edit control. It draws one extra pixel:



To fix this I changed the WADlg_DrawChildWindowBorders() function code a bit:

PHP Code:
if((0xffff0000) == DCW_SUNKENBORDER)
{
MoveToEx(ps->hdcr.leftr.bottomNULL);
LineTo(ps->hdcr.rightr.bottom);
MoveToEx(ps->hdcr.rightr.bottom 1NULL);
LineTo(ps->hdcr.rightr.top 1); 
WADlg_DrawChildWindowBorders() function cannot be used in WM_PAINT handler when in WM_PAINT already has some kind of drawing defined. Because the WADlg_DrawChildWindowBorders() is re-calling BeginPaint() function, it returns an empty HDC.
For my purposes I have fixed it.

Also when switching the focus between winamp windows, the edit control's borders are flickers.

Combobox cannot have a style CBS_DROPDOWNLIST because winamp doesn't skin the combobox's button.
It should be set CBS_DROPDOWN style instead.

PHP Code:
embedwnd.cpp file:
//line 233
HWND mlwnd=NULL;

if(!
IsWindow(mlwnd)) 
Here IsWindow() always takes NULL.
Ingvar is offline   Reply With Quote
Old 21st October 2022, 05:57   #24
thinktink
Forum King
 
thinktink's Avatar
 
Join Date: May 2009
Location: No longer on the streets of Kings County, CA.
Posts: 3,189
Version 1.3 (unauthorized) now available.

Changes:
  • Fixed always NULL condition as indicated by Ingvar in the ML window handle retrieval function: http://forums.winamp.com/showthread....32#post3227532
  • Updated reskin/refresh code to get consistent and expected results
  • Added "CreateSkinFont" function to load/reload the current skin's font
  • WM_SETFONT on every text displaying/handling control due to oddities
  • Added posting of WM_DISPLAYCHANGE during WM_INITDIALOG due to oddities
  • Added WM_APP handler to refresh certain aspects after skin switching completed as it wasn't working correctly all inside WM_DISPLAYCHANGE

Attached.
Attached Files
File Type: zip Nullsoft_Embedded_Window_Example_(Unauthorized)_v1_3.zip (157.0 KB, 42 views)
thinktink is online now   Reply With Quote
Old 21st October 2022, 06:03   #25
thinktink
Forum King
 
thinktink's Avatar
 
Join Date: May 2009
Location: No longer on the streets of Kings County, CA.
Posts: 3,189
Quote:
Originally Posted by Ingvar View Post
I tested your plugin (embedded window) and found that WADlg_DrawChildWindowBorders() function draws wrong borders for edit control. It draws one extra pixel:

...
It's not my function, it's part of the SDK, I can't change the SDK. To be honest, I'm not sure that's actually an error.


Quote:
Originally Posted by Ingvar View Post
Also when switching the focus between winamp windows, the edit control's borders are flickers.
I don't doubt that this is an issue for you, unfortunately I've not been able to replicate it to test.


Quote:
Originally Posted by Ingvar View Post
Combobox cannot have a style CBS_DROPDOWNLIST because winamp doesn't skin the combobox's button.
It should be set CBS_DROPDOWN style instead.
It seems to be working with CBS_DROPDOWNLIST fine for me, button and everything. Works on Windows 10 and Windows XP running inside Oracle VM VirtualBox.


Quote:
Originally Posted by Ingvar View Post
PHP Code:
embedwnd.cpp file:
//line 233
HWND mlwnd=NULL;

if(!
IsWindow(mlwnd)) 
Here IsWindow() always takes NULL.
Fixed in version 1.3. Thank you.
thinktink is online now   Reply With Quote
Reply
Go Back   Winamp & Shoutcast Forums > Developer Center > Winamp Development

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump