C++ and Win Api

Started by
5 comments, last by Coder88 14 years, 12 months ago
Hi, 1.) I have a small problem deciding which is better or am I doing it wrong. First I have 3 classes as follow:


class CS3DEDx9System
{
  //some stuff here
public:
  void dummyFunc();
};

class CS3DEWin32
{
  //Win stuff
public:
  void dummyFunc2();
};

class CS3DEDisplayManager: public IRunnable 
{
   public:
   // methods
   void Whatever();

   virtual HRESULT RunTask(); //this represent thread execution routine


private:

  CS3DEWin32     *win;
  CS3DEDx9System *dx;
};
   

This is some class that uses the DisplayManager


class MainInterface
{
   public:
    void DoSomething():

    CS3DEDisplayManager *DispMan;
};


Now the problem is when I was programming the Dx and Win class I tried for them to be as much isolated and self contained in order to use them again with out worrying about dependencies. Now time came to use them together in my small game engine library which in this case is the MainInterface class, and if i want to access a method in dx class for example than i need to wrap the method again in DispMan and this function would call the appropriate function; as follows:


CS3DEDisplayManager::Whatever()
{
   dx->dummyFunc();
}


Now this seems a lot of code needs to warped. Am I doing this wrong and insted should declare the dx and Win class a like this ?:


class CS3DEDisplayManager: public CS3DEDx9System, public: CS3DEWin32, public IRunnable


If you wondering why I use The In between class DispMan is becuase the DispMan class represents a thread that will execute and dx and win32 needs to be in the same thread plus I use no D3DMULTITHREAD flag so a lot of methods will be needed to be warped to make sure only the thread that created dx will run Resource Creation Code But the user will only deal with the maininterface class Is this the right approach or am I missing something? 2.) this should be easy for you guys but it gives me trouble


if( PeekMessage( &uMsg, NULL, 0, 0, PM_REMOVE ) )
{ 
	TranslateMessage( &uMsg );
       
        if(PeekMessage( &uMsg, hWnd, 0,0, PM_REMOVE)
        {
            if( uMsg.message == WM_SIZE)  //does not work
            {
               onWindowResize();
            }
        }

	DispatchMessage( &uMsg );
}


It does not work if I try to put this code after DispatchMessage or before TranslateMessage it never hits that OnWindowResize. The hWnd belong to the MainWindow any suggestions how to do this properly ? Thank you for any responses and reading this long post, if more info is required just let me know. ~Janusz
Advertisement
Quote:Original post by Coder88
2.) this should be easy for you guys but it gives me trouble

*** Source Snippet Removed ***

It does not work if I try to put this code after DispatchMessage or before TranslateMessage it never hits that OnWindowResize. The hWnd belong to the MainWindow any suggestions how to do this properly ?


The reason is that you are calling PeekMessage twice, overwriting the first event every time. This is the more approporiate way to do it (only one message check per time, if you want more, use a while instead for more efficiency):

if( PeekMessage( &uMsg, NULL, 0, 0, PM_REMOVE ) ){   if( uMsg.message == WM_SIZE)   {      onWindowResize();   }   TranslateMessage( &uMsg );   DispatchMessage( &uMsg );}


Also, if this is for a game, you will definitely want to have a look at this article: Writing the Game Loop. I'm sure there is more code, but depending on what you are doing, you might use some suggestions presented in that article.
My whole loop looks like this after I changed it but even with one PeekMessage it still don't work is this has something to do with Direct X ?

	while( uMsg.message != WM_QUIT )	{		if( PeekMessage( &uMsg, NULL, 0, 0, PM_REMOVE ) )		{ 			if(uMsg.message == WM_SIZE)			{				OnWindowResize(); //never called even if I resize window			}			TranslateMessage( &uMsg );			DispatchMessage( &uMsg );		}		else		{                    //Do stuff                }        }
Quote:Original post by Coder88
My whole loop looks like this after I changed it but even with one PeekMessage it still don't work is this has something to do with Direct X ?

*** Source Snippet Removed ***


Actually, that message cannot be handled there. I just checked a D3D basecode example, and they handle WM_SIZE inside their WndProc. What happens there in that case is you get WM_NCLBUTTONDOWN / WM_NCLBUTTONUP events, but a resize is actually dispatched to the window.

I don't know where you can get a list of what messages are allowed or not, but I'd just stick to WM_QUIT and handle anything else in the WndProc. The basecode I referenced was the simple D3D hosted on nehe's site (far right pane, middle of the page)
Thank you, I use the WndProc than, hehe some more warping of code =[ which brings me to question 1 any suggestions ?
I don't have many suggestions for you other than "don't over engineer it". I know it's popular and makes sense to try and abstract away your interfaces for reuse and a modern OOP approach, but most of the time you spend so much time working up a solution that seems nice, but you never end up actually reusing it. You will find some way to make it better or you will need to change it and if you are just trying to get a project off the ground it can be a bit of a distraction.

The Win32 API was not meant for use in a pure OOP design, so that's why you are seeing some problems trying to wrap it up nicely; it's tricky! It's still doable though, as long as you make use of SetWindoLong and GWL_USERDATA, you can pass a class pointer to the WndProc and then have the WndProc directly invoke some function with the parameters it has.

I'm not sure how much that actually helps though, but if you need a better explanation, let me know.
Quote:Original post by Drew_Benton

The Win32 API was not meant for use in a pure OOP design, so that's why you are seeing some problems trying to wrap it up nicely; it's tricky! It's still doable though, as long as you make use of SetWindoLong and GWL_USERDATA, you can pass a class pointer to the WndProc and then have the WndProc directly invoke some function with the parameters it has.

I'm not sure how much that actually helps though, but if you need a better explanation, let me know.


Yes I have something similar right now. In My win class which is part of the IDispMan class has the hole window creation and msg handling, once the class is created a static member is called which than calls the member Win32::WndProc, The user can register his callbacks via the class for handling msg such as keyDown, Size, etc...

The problem was that The Dx class needs to know when the WM_SIZE is sent so that it could re size the Back Buffer if required and the win class can only register one callback for WM_SIZE, but the solution was to add the callback to the dx class and that class would register Wm_SIZE in win32 class and add its own callback for the user, Am I making any sense ?

Quote:Original post by Drew_Benton


I don't have many suggestions for you other than "don't over engineer it". I know it's popular and makes sense to try and abstract away your interfaces for reuse and a modern OOP approach, but most of the time you spend so much time working up a solution that seems nice, but you never end up actually reusing it. You will find some way to make it better or you will need to change it and if you are just trying to get a project off the ground it can be a bit of a distraction.


true, but I Just wanted to have a small library that does not depend on other code so I can just grab this class and use it in another project without worrying about all the other dependencies, as before when I tried to use some code I basically ripped it form the project and than had do deal with a lot of errors / workarounds. But Now I am less strict on the OOP design and only isolate the classes the ones I will reuse most likely like Win32, Dx9, and Thread. Others not so much, just whatever makes it easier for them to play nice as you said "not to over engineer it".

thank for your response it made me think about the current design, and change it to what I described above.

This topic is closed to new replies.

Advertisement