|
OK, next question. I know how to subclass a window using SetWindowLong. No prob. However, the only way that I can find to do it, is to define a function outside of any class. Is there a way to use a function belonging to a class as the callback procedure, and if so, how do I declare it? Would it be:
m_OldWndProc=(WNDPROC)::SetWindowLong(m_ControlToSubclass.GetSafeHwnd(), GWL_WNDPROC, (LONG)CMyClass::NewWndProc);
Or, would it be
m_OldWndProc=(WNDPROC)::SetWindowLong(m_ControlToSubclass.GetSafeHwnd(), GWL_WNDPROC, (LONG)NewWndProc);
And, how do I properly cast the function point to the LONG that SetWindowLong requires for its 3rd parameter?
Also, what's the proper method of UN subclassing the window?
Thanks in advance for any help.
|
|
|
|
|
I infer from your GetSafeHwnd() calls that you're using MFC. If so, there's an easier way to do this - CWnd::SubclassWindow() .
But to answer your questions, you can't use CMyClass::NewWndProc() as the callback because that function has this as the first parameter (even though you don't write the function that way) which makes it not match the required prototype. If you make that member function static it will work, because static methods do not have a this pointer.
Also, to undo the subclassing, call SetWindowLong() again and set the wnd proc to m_OldWndProc .
|
|
|
|
|
Thanks. That makes sense. The only problem is that now I can't seem to access any members of the class, private, protected, or public (I assume that it's due to the lack of the 'this' pointer). I've never really played with CWnd::SubclassWindow, but I'll give it a go. Thanks.
|
|
|
|
|
Right, static functions can only access static members and other static functions of the class.
|
|
|
|
|
That is what the documentation says, but this is an example where the documentation is totally misleading. Just as a static function can access members of other classes, a static function is entirely capable of accessing members of it's own class.
Now I can hear you saying that I am quack or something like that, but I do it all the time. The thing that most people just do not realize is that you simply must provide to the static function (that does not have the "this" pointer) the pointer that it does not have. Very simple, yet it seems that many people overlook this and take the documentation too literally.
The trick of course is passing the pointer. Most callbacks and such have a parameter and the pointer can be passed as a parameter or part of a parameter. In the case of the situation being discussed, the solution is probably not so easy. It might be possible to use a solution simialr to MFC's solution to the equivalent problem. It is possible to create a mapping from the window handle to the pointer for the class. Right?
|
|
|
|
|
I'm using a Rich Edit control in my app to display output from a host.
I initially format the Rich Edit to use a black backgroud, white text, courier font etc... so that it looks like a terminal
windos. After that, I just dump the host messages to the control without formating.
Now for the question...
I have done this my associating a CString var with the Rich Edit. I write the host output to the CString and then update.
It seems to work fine.
However, I have read in several places that this is not a good idea. Why not?
Should I be using StreamIn with a callback? It seems like overkill for my needs.
Thanks!
Lori Mihalcik
|
|
|
|
|
Here's a question that I'm sure is going to be easy to answer. If I have an MDI application, how do I set up that first child window to be maximized on application start up? I'm sure I'm going to kick myself when I see the answer, but right now, I'm drawing a blank.
Thanks in advance.
|
|
|
|
|
Using MFC?
Well, that probably does not matter. If it is something you want to do only for the first child window, then InitInstance is probably a good possibility. You could just do a ShowWindow(SW_SHOWMAXIMIZED) for the the child, right?
|
|
|
|
|
Using ShowWindow works, except that when the application starts up, I can actually see the child being maximized. I'd like it to already be maximized on app start up (like when you start Word, the child window is already maximized). Thanks for the tip, though. Any ideas on how to get it maximized before you even see the app?
Again, thanks in advance.
|
|
|
|
|
Aha! Figured it out. Modify InitInstance as follows:
// The main window has been initialized, so show and update it.
CChildFrame *child=(CChildFrame *)pMainFrame->MDIGetActive();
child->ShowWindow(SW_MAXIMIZE);
pMainFrame->ShowWindow(m_nCmdShow);
pMainFrame->UpdateWindow();
Using ShowWindow was INDEED the correct way. I just stuck it in the wrong spot. Danke Zhen(Thank you)!
|
|
|
|
|
I knew you could. I knew that the positioning would make a difference and I considered whether to say something but I decided to assume you would figure it out.
|
|
|
|
|
Hello all.
If you're reading this, then you're either very knowledgeable about Dll programming or simply curious.
I'm trying to create my own Extension DLL.
Here's my code:
//MyClass.h
#ifndef _MYCLASS_HEADER_
#define _MYCLASS_HEADER_
class AFX_CLASS_EXPORT CMyClass : public CObject
{
DECLARE_DYNCREATE(CMyClass)
public:
// constructor
CMyClass();
// destructor
~CMyClass();
// some member functions
int getNumber();
void setNumber(int num);
protected:
private:
int m_iNumber;
};
#endif
// MyClass.cpp
#include "stdafx.h"
#include <afxdllx.h>
#include "MyClass.h"
static AFX_EXTENSION_MODULE MyClassDLL = { NULL, NULL };
extern "C" BOOL APIENTRY MyDllMain(HINSTANCE hInstance,DWORD dwReason,LPVOID lpReserved)
{
if (dwReason == DLL_PROCESS_ATTACH)
{
TRACE0("MyClass.DLL Initializing!\n");
// Extension DLL one-time initialization
AfxInitExtensionModule(MyClassDLL, hInstance);
// Insert this DLL into the resource chain
new CDynLinkLibrary(MyClassDLL);
}
else if (dwReason == DLL_PROCESS_DETACH)
{
TRACE0("MyClass.DLL Terminating!\n");
AfxTermExtensionModule(MyClassDLL);
}
return TRUE; // ok
}
IMPLEMENT_DYNCREATE(CMyClass, CObject)
// my class member definitions here...
Ok. So that's my code. I want to be able to instanciate the CMyClass class from the resultant Dll.
Unfortunately, when I try to link this into a proper Dll, I get the following error:
mfcs42d.lib(dllmodul.obj) : error LNK2005: __pRawDllMain already defined in MyClass.obj
The entry-point for this Dll is specified as MyDllMain in the Project->Settings->Link->EntryPoint.
What does this error REALLY mean? What do I have to do to make it work?
It's worth noting that I have a sample from a book which is very similar to the above code and it links
to a Dll beautifully. Is there a linker option that needs to be set for my code to link properly?
Thanks for your help!
Regards,
dogBear
|
|
|
|
|
How is the Myclass.obj file being linked in? For your DLL project you should only have to include the Myclass.h in some .cpp file and during the link operation have the Myclass.lib file searched.
|
|
|
|
|
I have been trying to use the CListViewCtrl from "atlcontrols.h". In my class Ihave this:
CContainedWindowT<atlcontrols::clistviewctrl> m_InfoList;
Now this compiles just find and as far as I know this sould work. Now in my .cpp file I create the control by doing this.
// Initialize the CListViewCtrl
RECT Rect = {100, 100, 200, 200};
m_InfoList.Create (m_hWnd, Rect, "VersionInfoList", WS_CHILD);
m_InfoList.SetExtendedStyle (LVS_EX_GRIDLINES);
m_InfoList.ShowWindow (SW_SHOW);
This is where the problem occurs. I get an error (C2664) stating that my first parameter "m_hWnd" cannot be converted to an ATL::MessageMap. What am I doing wrong here? Any help on this would be great.
Thanks
|
|
|
|
|
Ooops, here is the first line of code
CContainedWindowT "ATLControls::CListViewCtrl" m_InfoList; The greater than and less than signs should be substituted for the open and close quotes.
|
|
|
|
|
have you any idea what can be wrong in this code?
it is part of printig code and only code part i'm working with bitmap
works fine under nt or 2000
under w9x displays 25 and crashs (before it long code with TextOut lives)
thanks
t!
HINSTANCE hResourceDll = ((CLayerdllApp*)AfxGetApp())->m_hAllgResourceDll;
HBITMAP hBmp = (HBITMAP)::LoadImage( hResourceDll == NULL ? AfxGetInstanceHandle() : hResourceDll,
MAKEINTRESOURCE(nImageID), IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION | LR_DEFAULTSIZE
);
CBitmap StatusBitmap;
StatusBitmap.Attach(hBmp);
CDC dcMemory;
dcMemory.CreateCompatibleDC(pDC);
if(dcMemory.m_hDC == NULL)
MessageBox("22a");
CBitmap* pOldBitmap = (CBitmap*)dcMemory.SelectObject( StatusBitmap);
if(StatusBitmap.m_hObject == NULL)
MessageBox("23a");
if(pOldBitmap == NULL)
MessageBox("23b");
MessageBox("25");
dcMemory.SelectObject(pOldBitmap);
MessageBox("26");
|
|
|
|
|
seems i found it!
change
CBitmap* pOldBitmap
to
HBITMAP pOldBitmap
t!
|
|
|
|
|
Hello,
I wonder if there is a function like SendKeys function in VC++.
İf not, how can i send keystrokes to other applications? Do i have to use SendMessage or PostMessage functions?
Mustafa Demirhan
|
|
|
|
|
Yes you should use
SendMessage or PostMessage
Something like
SendMessage(h_yourWnd,WM_KEYDOWN,...)
you should chek help for WM_KEYDOWN message to get info about parameters
regards,
/REMUS
|
|
|
|
|
Yes, but be sure to send WM_KEYUP messages for each character just after each WM_KEYDOWN, maybe with some delay.
|
|
|
|
|
Look up the keybd_event() and SendInput() APIs.
|
|
|
|
|
Hello,
I have a big problem about modeless dialogs. When i create the dialog like
CString msg("Message");
CShowMessage *swRem=new CShowMessage(msg);
swRem->Create(IDD_SHOWMESSAGE_DIALOG);
swRem->ShowWindow(SW_SHOW);
it works fine.(This dialog gets a string as a parameter).
However, if i call it like this
CString msg("Message");
CShowMessage swRem(msg);
swRem.Create(IDD_SHOWMESSAGE_DIALOG);
swRem.ShowWindow(SW_SHOW);
it appears first but then immediately dissappers.
This is a big problem since i have to delete the new dialog if i use the first code. To delete this dialog, i pass the pointer of the dialog to itself as a parameter and the dialog deletes itself. However, this is not a good programming practice.
I need your suggestions.
Mustafa Demirhan
|
|
|
|
|
Usually disapears because the scope of variable
swRem is finished.
The best way is the first solution and on WM_CLOSE message (should be more) try a "delete this"
It should work.
regards,
/REMUS
|
|
|
|
|
Actually, the delete this; call should go in an override of PostNcDestroy() .
|
|
|
|
|
I suspect that your code :
CString msg("Message");
CShowMessage swRem(msg);
swRem.Create(IDD_SHOWMESSAGE_DIALOG);
swRem.ShowWindow(SW_SHOW);
is in some function. Once the function returns,
static local variables are automattically destroyed.
(in your case , msg and swRem).
One thing to try is to make these variable global by
putting the lines :
CString msg("Message");
CShowMessage swRem(msg);
at the top of your CPP file.
|
|
|
|