Does this constructor return a instance? - c++

virtual BOOL Create(
LPCTSTR lpszCaption,
DWORD dwStyle,
const RECT& rect, //we need to pass a RECT instance
CWnd* pParentWnd,
UINT nID
);
// Create a push button.
myButton1.Create(_T("My button"), WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON,
CRect(10,10,100,30), pParentWnd, 1);
CRect(10,10,100,30) is a constructor,does this mean the constructor return a instance?

//CRect(10,10,100,30) is a constructor...
No it is not. It is the declaration of an object. It does call the constructor but the object is created locally, not returned by the constructor.

This code is equivalent to the following :
CRect rect = CRect(10,10,100,30);
// Create a push button.
myButton1.Create(_T("My button"), WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON,
rect, pParentWnd, 1);
The constructor returns an instance of the class it is constructed, which is used by the Create function.

Related

How to incorporate a pImpl Interface while also allowing WndProc to interact with it?

Currently developing a 2-D game-dev environment with a Wrapper/GameEngine class combination in Win32 (C/C++ language). As it stands, I use the Wrapper to set up and initialize all items with the Window as well as to initialize the GameEngine class before entering the message loop.
To do this, I redirect Windows messages sent to WndProc(...) to HandleEvent(...) methods found in both the Wrapper and the GameEngine classes. This is done via static, private shared_ptrs found in the Wrapper class. One such pointer points to the contained GameEngine, and the other points to the Wrapper itself.
An example WndProc function may look like this:
LRESULT CALLBACK WndProc(HWND hWindow, UINT msg, WPARAM wParam, LPARAM lParam)
{
// Initialize via wrapper, else route to engine
switch (msg)
{
case WM_CREATE:
return GEN::Wrapper::GetWrapper()->HandleEvent(hWindow, msg, wParam, lParam);
break;
default:
return GEN::Wrapper::GetEngine()->HandleEvent(hWindow, msg, wParam, lParam) // DefWndProc called from this HandleEvent
}
}
Where GetEngine() and GetWrapper() are static accessor methods that return their respective shared_ptr.
What I'd like to do is incorporate the pImpl idiom in this design. That is, I want to create a wrapper interface class that removes implementation details from the specific wrapper being used. One of the problems ailing me is that I need (or at least think I need) that static accessor method for the Wrapper in question. This is because as I have it each derived Wrapper initializes the window in a game-specific way, and WndProc needs to know where to forward that initial message, as one can see in the code above. Of course, the static method is tied to the wrapper class, so GetWrapper() would be impossible to put into that interface.
Essentially, I want to have the WrapperInterface declared like this:
class WrapperInterface
{
public:
static std::tr1::shared_ptr<WrapperInterface> // factory function
create_Wrapper(...); // returns pImpl
// ... Pure virtuals here
};
Derive Wrapper publicly from WrapperInterface, and then implement a primitive version of create_Wrapper more or less like this:
std::tr1::shared_ptr<WrapperInterface> WrapperInterface::create_Wrapper(...)
{
return std::tr1::shared_ptr<WrapperInterface>(new Wrapper(...));
}
so I can put this line in WinMain:
std::tr1::shared_ptr<WrapperInterface>
Wrapper(WrapperInterface::create(...));
And still have WndProc be able to forward messages to the Interface methods?
Update:
A thought occurred to me to store a static pointer to the WrapperInterface itself and have create_wrapper set that member variable to whatever wrapper the interface is using. I then eliminated Wrapper's static pointer altogether and made the Engine pointer non-static. This somehow feels like cheating, though, as now I'm introducing a private member variable into the interface, albeit a static one. Any thoughts or tips on redesign methods without storing statics would be great!
In any event, thank you all for reading and any advice you may give.
You can associate a pointer to the actual Wrapper object with the window that it creates for itself. To do that, you can either:
use RegisterClass/Ex() with the cbWndExtra field set to sizeof(Wrapper*) to reserve extra memory inside the HWND, then use SetWindowLong/Ptr() with the nIndex parameter set to 0 to store the Wrapper* pointer value inside the allocated memory:
WNDCLASS wc;
wc.lpszClassName = TEXT("MyWrapperWindow");
wc.cbWndExtra = sizeof(Wrapper*);
...
RegisterClass(&wc);
hwnd = CreateWindow(TEXT("MyWrapperWindow"), ...);
SetWindowLongPtr(hwnd, 0, (LONG_PTR) this);
use SetWindowsLong/Ptr() with the nIndex parameter set to GWLP_USERDATA:
hwnd = CreateWindow(...);
SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR) this);
use SetProp() with a custom name in the lpString parameter:
static const LPCTSTR szMyProp = TEXT("MyProp");
hwnd = CreateWindow(...);
SetProp(hwnd, szMyProp, (HANDLE) this);
use SetWindowSubclass() with the Wrapper* pointer passed in its dwRefData parameter:
hwnd = CreateWindow(...);
SetWindowSubclass(hwnd, &MySubClassProc, 1, (DWORD_PTR) this);
In cases 1-3, at least (not sure about case 4), you can alternatively pass the Wrapper* pointer in the lpParam parameter of CreateWindow/Ex() and then call one of the mentioned functions inside your window procedure's WM_NCCREATE or WM_CREATE handler:
hwnd = CreateWindow(..., this);
case WM_CREATE:
{
Wrapper *pThis = (Wrapper*) ((LPCREATESTRUCT)lParam)->lpCreateParams;
// SetWindowLongPtr(hwnd, 0, (LONG_PTR) pThis);
// SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR) pThis);
// SetProp(hwnd, szMyProp, (HANDLE) pThis);
break;
}
For all other messages, your window/subclass procedure can extract the Wrapper* pointer when needed. This way, it does not need to use any global statics to hunt for the object:
GetWindowLong/Ptr() with the nIndex parameter set to 0:
Wrapper *pThis = (Wrapper*) GetWindowLongPtr(hwnd, 0);
GetWindowsLong/Ptr() with the nIndex parameter set to GWLP_USERDATA:
Wrapper *pThis = (Wrapper*) GetWindowLongPtr(hwnd, GWLP_USERDATA);
GetProp(), passing the same lpString pointer that was passed to SetProp() (important!):
Wrapper *pThis = (Wrapper*) GetProp(hwnd, szMyProp);
the subclass procedure's dwRefData parameter:
Wrapper *pThis = (Wrapper*) dwRefData;

paint background in mfc

I am experimenting with painting the background of a window in c++ using the MFC library. It is mandated that i use this framework because I am working on an MFC application. I have tried several different methods but cannot get it to work. So i recently opened a blank project and just want to figure out how to paint the background but it is not working. Any help would be great. Here is my code...
class CExerciseApp : public CWinApp
{
//a pointer to our window class object
Basic_Window *bwnd;
BOOL InitInstance()
{
bwnd = new Basic_Window();
m_pMainWnd = bwnd;
bwnd->ShowWindow(1);
HWND hWnd = GetActiveWindow();
CRect drawing_area;
GetClientRect(hWnd, &drawing_area);
CBrush newBrush;
newBrush.CreateSolidBrush(RGB(255,255,255));
CDC* dc = bwnd->GetDC();
dc->FillRect(&drawing_area, &newBrush);
bwnd->RedrawWindow();
return TRUE;
}
};
From my own post https://stackoverflow.com/a/22875542/383779 , I can guarantee I had made that work. I used that approach for implementing themes/skins on a commercial application.
You need to add a OnCtlColor method to your Basic_Window class.
In your .h file, add to the Basic_Window class:
const CBrush m_BackgroundBrush;
and
afx_msg HBRUSH OnCtlColor( CDC* pDC, CWnd* pWnd, UINT nCtlColor);
In .cpp file the constructor will initialize the new variable
Basic_Window::Basic_Window()
: m_BackgroundBrush(RGB(255,255,255))
{
//...
}
and implement
HBRUSH Basic_Window::OnCtlColor( CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
if(some_exception)
return __super::OnCtlColor( pDC, pWnd, nCtlColor);
return (HBRUSH) m_BackgroundBrush.GetSafeHandle();
}
some_exception here means a situation where you will want the default behavior, instead of your own painting. Maybe it is a certain type of control, and for that exists the nCtlColor parameter.
Do not forget to add ON_WM_CTLCOLOR() to your message map.

Must a pointer to an instance of class A be static in class B?

IDE: Eclipse Juno;
Compiler: MinGW 4.6.2;
Project: Win32
I have a MainWindow with two somewhat-dissimilar MDI child windows: MdiChildWindowA and MdiChildWindowB. A third child window, SharedWindow, is not MDI but can be used by either MDI child window. All are encapsulated in their own C++ classes.
To avoid proliferation of SharedWindow, I borrowed part of the singleton design: MainWindowClass::GetSharedWindowInstance() will return a pointer to an instance of SharedWindow, creating one if one doesn't already exist. MainWindow.h includes SharedWindow* pSharedWindow to back up the function. (That's as close as SharedWindow gets to being a singleton.)
When MainWindow instantiates MdiChildWindowA and MdiChildWindowB, it passes this to their constructors, which they save in the class variable pMainWindow (defined as MainWindow* in MdiChildWindowA.h and MdiChildWindowB.h).
cout of this in MainWindow matches cout of pMainWindow in the MDI child window constructors, but by the time another function calls pMainWindow->GetSharedWindowInstance(), pMainWindow has changed! Making pMainWindow static seems to have solved the problem but how did pMainWindow change?
Similarly, I found that HMODULE and LPPICTURE variables had be static in SharedWindow.h or they would forget their values between functions in SharedWindow.cpp. Are pointer types somehow exempt from persistence as class variables? I thought static was meant to ensure one value across all instances of its class.
Edit 2013-Sep-04:
Below is my Application.cpp (largely copied from a tutorial). I thought my MainWindow instance was created on the heap and would persist until exiting.
#include "MainWindow.h"
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrev, LPSTR lpCmdLine, int nCmdShow )
{ MSG msg;
HWND hMdiClientWindow;
MainWindow *winMain = new MainWindow( hInstance );
if( !winMain->Run( nCmdShow ) )
{ delete winMain;
return 1;
}
hMdiClientWindow = winMain->GetMdiClientWindow();
while( GetMessage( &msg, NULL, 0, 0 ) )
{ if( ! TranslateMDISysAccel( hMdiClientWindow, &msg ) )
{ TranslateMessage( &msg );
DispatchMessage ( &msg );
}
}
delete winMain;
return msg.wParam;
}
new MainWindow(...) invokes MainWindow::MainWindow(), where cout shows this is 0xdd13a0.
MainWindow is created in the call to Run(...), which passes the pointer to the instance of MainWindow in lpParam:
bool MainWindow::Run( int nCmdShow )
{ ...
hMainWindow = CreateWindowEx( ..., this );
...
}
In the window procedure, the pointer is saved in the instance data of MainWindow:
LRESULT CALLBACK MainWindow::MainWindowProcedure( HWND hMainWindow, UINT Msg, WPARAM wParam, LPARAM lParam )
{ MainWindow* pThis;
if( Msg == WM_NCCREATE )
{ CREATESTRUCT* pCreateStruct = (CREATESTRUCT*) lParam;
pThis = (MainWindow*) pCreateStruct->lpCreateParams;
SetWindowLongPtr( hMainWindow, GWL_USERDATA, (LONG) pThis );
} else
{ pThis = (MainWindow*) GetWindowLongPtr( hMainWindow, GWL_USERDATA );
}
In WM_CREATE, cout shows pThis is 0xdd13a0 when it's passed to the constructors of MdiChildWindowA and MdiChildWindowB:
switch( Msg )
{ ...
case WM_CREATE:
{ unique_ptr<MdiChildWindowA> upMdiChildWindowA;
unique_ptr<MdiChildWindowB> upMdiChildWindowB;
...
up_MdiChildWindowA = unique_ptr<MdiChildWindowA>( new MdiChildWindowA( m_hInstance, pThis, [window dimensions] ) );
up_MdiChildWindowB = unique_ptr<MdiChildWindowB>( new MdiChildWindowB( m_hInstance, pThis, [window dimensions] ) );
The constructors of the MDI child windows copy the MainWindow pointer in the parameter pMainWindow into the class variable m_pMainWindow, and cout shows that both contain 0xdd13a0:
MdiChildWindowA::MdiChildWindowA( HINSTANCE hInstance, MainWindow* pMainWindow, ... )
{ m_pMainWindow = pMainWindow;
....
}
In WM_CREATE of the MDI child window procedure, cout shows m_pMainWindow still contains 0xdd13a0. The only other reference to m_pMainWindow occurs in WM_LBUTTONDBLCLICK where, unless I've made it static, it has somehow become 0xdd1380 (perhaps during a pass through DefMDIChildProc(...)?):
MdiChildWindowA::MdiChildWindowProcedure( ... )
{ ...
switch( ... )
{ ...
case WM_LBUTTONDBLCLICK:
{ SharedWindow* pSharedWindow;
...
pSharedWindow = pThis->m_pMainWindow->GetInstanceOfSharedWindow(); // pThis points to this instance of MdiChildWindowA. cout confirms its value hasn't changed.
Since m_pMainWindow is pointing to the wrong place, the program crashes when a SharedWindow function is called via pSharedWindow. It appears however that GetInstanceOfSharedWindow() exists in this bogus instance of MainWindow because an address is returned - but, in the code above, it's the address of MdiChildWindowA!
(Note: my naming convention drives people nuts so I re-typed the code with less-dangerous names. Hopefully there are no typos.)
#brunocodutra, #Chris Hayes: I don't have enough points to comment yet, but I appreciate your ideas.
Hard to tell without the full relevant code, but I would guess MainWindow is being deallocated. I would further guess MainWindow is originaly stored in the stack, rather than the heap, because what causes the address to change is a function call (which alters the stack).
My advice: verify if either MainWindow or MdiChildWindowA and MdiChildWindowB (not sure which pMainWindow changes) are local variables and if so, change your code, so that they get allocated in the heap, i.e. dynamicaly through the use of the keyword new.
Answering the second question, pointers are not treated differently from any other type, in essence they are very much like integers, but their content is promptly allowed to be interpreted as memory addresses.

How do I add an edit box to MFC CFolderDialog ("browse for folder" dialog)?

I currently have a CFolderDialog class that is used in my CDocManagerEx class for handling file operations as follows:
alt text http://img268.yfrog.com/img268/9271/filedialog.png
I don't know if I need to show the method implementation of this class (I found this from a project posted here), but here is the class definition if it helps:
class CFolderDialog
{
friend static int CALLBACK BrowseDirectoryCallback(
HWND hWnd, UINT uMsg, LPARAM lParam, LPARAM lpData);
public:
CFolderDialog( LPCTSTR lpszFolderName = NULL,
DWORD dwFlags = NULL/*BIF_RETURNONLYFSDIRS*/,
CWnd* pParentWnd = NULL);
virtual ~CFolderDialog();
virtual int DoModal();
CString GetPathName() const;
protected:
virtual void OnInitDialog();
virtual void OnSelChanged(ITEMIDLIST* pIdl);
virtual void CallbackFunction(HWND hWnd, UINT uMsg, LPARAM lParam);
void EnableOK(BOOL bEnable = TRUE);
void SetSelection(LPCTSTR pszSelection);
void SetSelection(ITEMIDLIST* pIdl);
void SetStatusText(LPCTSTR pszStatusText);
CString ShortName(const CString& strName);
public:
BROWSEINFO m_bi;
protected:
CString m_strInitialFolderName;
CString m_strFinalFolderName;
TCHAR m_szDisplayName[MAX_PATH];
TCHAR m_szPath[MAX_PATH];
HWND m_hDialogBox;
};
class CMyFolderDialog : public CFolderDialog
{
public:
CMyFolderDialog(LPCTSTR lpszFolderName = NULL,
DWORD dwFlags = NULL,
CWnd* pParentWnd = NULL,
LPCTSTR pszFileFilter = NULL);
virtual ~CMyFolderDialog();
protected:
virtual void OnSelChanged(ITEMIDLIST* pIdl);
protected:
CString m_strFileFilter;
};
My goal of this question is adding an edit control to the window just below the workspace where the directory is selected. What would be the easiest way to accomplish this?
If you just want an edit control that allows the user to type in the name of a directory entry, that is possible. The C++ class you're using is a wrapper round the Win32 SHBrowseForFolder() method, and that method supports having an edit box by setting the BIF_EDITBOX (or better, BIF_USENEWUI) in the ulFlags member of the BROWSEINFO structure.
Looking at the C++ class, it looks like the simplest way to achieve this will be to pass BIF_USENEWUI as the dwFlags member in the constructor call. (Though I'd be tempted to just call SHBrowseForFolder directly and not bother with the C++ class.)
Do note the warning about this flag in MSDN, though: OleInitialize() or CoInitialize() must have been called before bringing up the dialog with this flag.
More generally, if you want an edit control that you can use for your own purposes, allowing the user to enter anything, that's more of a problem: there's no way to extend the dialog used by SHBrowseForFolder() with custom controls. If you want to do that, you'd end up having to re-implement the whole dialog, which isn't a good idea.
Also, as a final note, if you can limit yourself to Vista (and beyond) then there's another way to have a directory selection dialog: use the new IFileDialog COM interface, with the FOS_PICKFOLDERS flag.
Maybe some of the ideas in this will do what you want?
http://www.codeproject.com/KB/dialog/browse_for_folder_dialog.aspx
or this
http://www.codeguru.com/cpp/w-p/files/browserfunctionsdialogs/article.php/c4443

Setting Background Color CMDIFrameWnd

Is there a way to change the color of the background for a MDIParent windows in MFC (2005)?
I have tried intercepting ON_WM_CTLCOLOR AND ON_WM_ERASEBKGND but neither work. OnEraseBkgnd does work, but then it gets overwritten by the standard WM_CTL color.
Cheers
Create a class deriving CWnd (CClientWnd for example)
In your CWnd-derived class handle
afx_msg BOOL OnEraseBkgnd(CDC* pDC);
afx_msg void OnPaint(void);
afx_msg void OnSize(UINT nType, int cx, int cy);
You need the following message map entries:
ON_WM_ERASEBKGND()
ON_WM_PAINT()
ON_WM_SIZE()
In OnEraseBkgnd just return TRUE, you'll do all of the work in OnPaint
In OnPaint, do whatever you like. To fill with a color, you could do
CBrush brush;
brush.CreateSolidBrush(COLORREF(RGB( 80, 160, 240 )));
CRect clientRect;
GetClientRect(clientRect);
CPaintDC dc(this);
dc.FillRect(clientRect, &brush);
In OnSize, call the base class, then invalidate to force a repaint:
CWnd::OnSize(nType, cx, cy);
Invalidate(FALSE);
In your mainframe, declare a member CClientWnd (m_clientWnd for example)
In your mainframe's OnCreate, first call the superclass, then
m_clientWnd.SubclassWindow(m_hWndMDIClient);
The CMDIFrameWnd is actually covered up by another window called the MDIClient window. Here is a Microsoft article on how to subclass this MDIClient window and change the background colour. I just tried it myself and it works great.
http://support.microsoft.com/kb/129471
There appears to be a simple solution to this problem in VS2008 at least:
In
CMainFrame::OnPaint()
{
..
// get the dc of the background window
CWnd* pWnd = CWnd::FromHandle(m_hWndMDIClient) ;
CPaintDC dc1(pWnd) ;
//and then draw or bitblt in this DC
}
Just guessing here, but try handling ON_WM_PAINT.