Win API based Custom Control in a DLL

Hi!

I have don this thing before using VC++ and MFC. But my new owner :) don't want to use VC++. So I decided to port the whole thing to Win API. Generally this should be easy, but I have problems with the DLL part somehow.

When I make a basic DLL with only the dll_process_attach and just the initalization and some mouse handling, the DLL works! But when it's got basic TLS code to save my custom control class address for multithreadding support, it just don't work. The test app isn't start at all - and it isn't shows up in the TaskManager. AND where I got confused. If I comment all the added lines it still not change a thing. Even if I clear all generated files and recompile.

Did someone do this before? Dose anyone have a template to this? I confused because I did done it in VC++ and it's working.

Please help! Thx!
Ok! The basic problem is solved. I have forgotten to change the class name in the resource.

Btw the TSL thing isn't working how it's presented in the Win API programming help file. So if someone has working solution for DLL with TSL - or a way to store an address of the class for every thread - I need it badly!

Realy, I don't know if I need to do this TSL thing for running different instances of a control, but if not, then how to store the class's address?

Thx for any help!
I've never personally used threads in my custom controls, or handled the thread attach/detach messages. Are you sure you need to do this? If you don't, it sounds to me like your problem is solved.

The basic idea of custom windows controls is that the window class is registered in the dll and thereby made available to hosts through your basic CreateWindowEx() Api call. Its not a requirement that the code be in a dll but that is what most folks want. In any case, the critical issue, and where almost everyone falls flat on their face, is through their failure to handle 'instance data' correctly. You generally need to perform memmory allocations for each instance of a control created by a client/host; you need to associate this instance data with each HWND; and you are likely not going to use threads for this. I don't know if I'm answering your question or not.
Sounds to me that freddie1 is correct. Why do you need thread local storage anyway? What class' address are you saving? Remember that windows are meant to be accessed by the thread that creates them only. The usual way to associate a C++ class instance (a. k. a., an object) to a window is storing the object's address in the window extra memory.
Basically I made a class for message handling and information storing - like boarder size, text size, color and stuff like that. And that address must be saved somehow to access the data in the class. It can be done in a global variable, but I don't think that is an elegant solution. I want to do this right because this can be a template afterwards.

I clearly stated that I don't know if I really need to use threads in my control. But I assume if a dll is loaded to memory, every program attach to that instance and if the class address is in a global variable, every program shares the same data too. This data must be unique for all instances of the control. So the question is: How to elegantly store unique information for all instances of a custom control in a DLL? :)

Thx for the fast replies!
You are laboring under some false assumptions RawBits.

First, every process that loads your Dll will have fresh instances of all variables in the Dll - even globally defined data.

Secondly, if you are creating a 'control' as opposed to something that just does data crunching, then there is a window class that needs to be registered for the control. Your host/client should then be able to create an instance of the control through a CreateWindowEx() function call where the class name of your control is passed in through the szClassName parameter of the call. At the point of the CreateWindowEx() call on the custom control registered in the dll the created object will receive a WM_CREATE message. The Window Procedure for the custom control should be in your dll. In the WM_CREATE handler you need to perform a memory allocation for whatever 'state' data your control needs to do whatever it does. Here is an example. I'm clueless what your control does, but lets say every instance of it needs to maintain a unique integer value and a unique character string. Then make a struct like so...

1
2
3
4
5
struct Something
{
  int iSomeNumber;
  TCHAR szSomeString[64];
};


Then, in your WM_CREATE handler, which will be called exactly once for each instance of a control created, you will do a memory allocation for a Something struct, and store the pointer to that memory either within the Window Class structure througfh the WNDCLASSEX::cbWndExtra bytes, or through Window Properties, i.e., GetProp() / SetProp().
For example...

1
2
3
4
5
6
7
Something* pSomeThing=NULL;

pSomeThing=(SomeThing*)GlobalAlloc(GPTR,sizeof(Something));
if(pSomething)
{
  SetWindowLong(hWnd,0,(long)pSomething);
}


In your WM_DESTROY handler you need to release any allocated memory.

Using this technique every instance of your control will maintain 'state' and be seperate from every other instance.
Thx freddie1! Kudos!

I'll try that WNDCLASSEX::cbWndExtra thing and reply with the outcome next week. I'm not too good at WinAPI because I don't like PC programming since .NET and Java rules in the business. I program only algorithms and recently Nintendo handhelds.

The control does it does some crazy stuff on many channels of data and do representations from them and allow to visually select, edit the data directly and save it. It's pretty complex...
I favor a variation of freddie's approach. I store the window instance data in a HWND -> instance map. That way the data is not in danger of being trampled on if the client app inadvertently uses SetWindowLong/SetWindowLongPtr with the same index. It also make clean-up code easier to write.
Last edited on
I have used the userdata field with SetWindowLong() and because I use only and directly the WinAPI, I can assume there is no function that uses that field for whatever reason.

Sorry I've got a higher priority project which doesn't uses this conrtol in the current state. But I'll work on it in my spare time and paste the working template here. In theory It's working like freddie1 sad before and the loaded DLL uses always the same copy of the code in memory every time it's loaded, but geting a new memory for every variable - even global ones - in the DLL. I only used the userdata field, becouse every window has exactly one instance of the same class, so they logically belong to each other.
Topic archived. No new replies allowed.