|
You can search for a window handle or a CWnd object by using the FindWindow-function.
When the call returns, you have either a pointer to CWnd representing this window (MFC version) or the window's HWND (API version). Then you can use this HWND e.g. to change window title by using SetWindowText-function, or if you use the MFC-version, you can use the CWnd to mess around with the window just as if you would have created it yourself. Change status bar, toolbar, menu, layout, minimize, maximize etc etc
What exactly is it that you want to do with the current time and date ? Should the target window display this on it's status bar ? Or draw it somewhere else inside it ? Want to hijack a window's Device Context ? Explain. The 'Send the current time and date to the bottom' isn't very informative
-Antti Keskinen
----------------------------------------------
The definition of impossible is strictly dependant
on what we think is possible.
|
|
|
|
|
well, basically i want to add the current time and date to the bottom of the page in all open notepad windows, save and close them.... to remember where i left off at, and what date/time i was reading it.... but this is just for knowledge.. im not going to make a nice program out of it... just experimenting :-/
|
|
|
|
|
Ahh ok.
Let's create a general outline of the solution to this problem.
1. Find the window
2. Enumerate the views of this window
3. With each view, access the underlying document
4. Get this document's CString, and append the current date and time to the end.
5. Force window to save all it's open documents/views.
For a specific, Notepad-only solution, the outline is a bit different, because Notepad doesn't have any real views: it has one HUGE edit control.
Now, some code pieces. With the MFC-way, of course
<br />
CWnd* pNotepadWin = new CWnd;<br />
<br />
HWND hwndNotepad = ::FindWindow( ClassName, NULL ) );<br />
<br />
if ( hwndNotepad )<br />
{<br />
pNotepadWin->Attach( hwndNotepad );<br />
}<br />
else<br />
{<br />
delete pNotepadWin;<br />
return FALSE;<br />
}<br />
<br />
Now we have the CWnd representation of the Notepad window.
<br />
CWnd* pNotepadEdit;<br />
<br />
pNotepadEdit = pNotepadWin->GetTopWindow();<br />
<br />
if ( !pNotepadEdit )<br />
{<br />
pNotepadWin->Detach();<br />
<br />
delete pNotepadWin;<br />
return FALSE;<br />
}<br />
<br />
bool bContinue = true;<br />
while ( bContinue )<br />
{<br />
CString strName;<br />
<br />
::GetClassName(pNotepadEdit->m_hWnd, (LPTSTR) strName, 20);<br />
<br />
if ( strName.CompareNoCase("Edit") == 0 )<br />
bContinue = false;<br />
<br />
pNotepadEdit = pNotepadEdit->GetNextWindow(GW_HWNDNEXT);<br />
<br />
if ( !pNotepadEdit )<br />
{<br />
bContinue = false;<br />
}<br />
}<br />
<br />
Phew. That was some coding. But now we have the CWnd of the edit control inside Notepad. After this, it's easy to use 'GetWindowText' and 'SetWindowText' to append the current date and time to the edit control's contents.
Perhaps I should turn this into an article
-Antti Keskinen
----------------------------------------------
The definition of impossible is strictly dependant
on what we think is possible.
|
|
|
|
|
What a perfect world it could be with out errors.
Going forth in a software developement I got to an error which I could not find a resource that give an answer.
It's about templates, and I must tell you that I'm new in this stuff.
Consider 'ClassA' which requiers template list when you want to define a object of it. Like this:
ClassA<long> obj;
And Consider another class that is the same to the previous one, 'ClassB' (with template list).
Now here's the problem, how can you define an object of 'ClassA' with the template list of 'ClassB' type, it should be something like this:
ClassA<ClassB> obj;
But compiler tells me that it has an error becuase 'ClassB' requiers a list of templates. So I thought that it might be defined like this:
ClassA<ClassB<long>> obj;
Now it has an another error:
error C2146: syntax error : missing ',' before identifier 'obj'
Well how can I define an object from a class with template list of sort of a class with template list?
|
|
|
|
|
Hi
The solution is pretty simple.
In stead of
ClassA<ClassB<long>> obj;
use
ClassA<ClassB<long> > obj;
Yes, the only difference is a space. The reason for the error is that the compiler finds '>>' and believes it to be the >> operator instead of the end of the template lists. So if you put in a space, the first > will end the inner template list and the second the outer and the compiler is happy.
|
|
|
|
|
Hello everybody,
I'm reading a .jpg file, everything goes fine, readhuge reports reading the hole file but what I've got in the buffer is just 4 bytes. What is ReadHuge reading ?
code:
buffer = new char[1000000];
if (buffer == NULL)
{
cout<<"Not enough memory";
return;
}
try
{
imageFile.Open(fileTitle,CFile::modeRead,&e);
imageFile.ReadHuge(buffer,1000000);
imageFile.Close();
CString output = header + buffer;
imageFile.Open("msg01",CFile::modeCreate | CFile::modeWrite,&e);
imageFile.WriteHuge((LPCTSTR) output,output.GetLength());
imageFile.Close();
delete []buffer;
}
|
|
|
|
|
The jpg contains binary NUL characters; your output = header + buffer statement will append the buffer up to the first NUL byte (or WORD, if you're using UNICODE), so GetLength() isn't giving you a big enough number.
Steve S
|
|
|
|
|
How to restore (maximize) my application instead of running a new instance when another instance is already running?
|
|
|
|
|
You could try to define a hook to maximize your app when you do smtg ... Or you could hit ALT-TAB
|
|
|
|
|
|
Somehow, before you create your app window, you need to find if another instance is running. One way is to use a named mutex that each instance tries to aquire. Another is to use the main window text as shown below (although not the suggested method) :
HWND h = ::FindWindowW(AppName, NULL);
if( h ) {
::SetForegroundWindow( (HWND)((ulong)h|0x00000001) );
return(true);
}
The key point in the above is not finding the app window, but how to restore it once found.
...cmk
Save the whales - collect the whole set
|
|
|
|
|
Working with the Wizzard, I define the PreCreateWindow function - and it never gets the control.
Does anyone have an idea, why not?
|
|
|
|
|
I assume you use MFC here.
There, the PreCreateWindow is a virtual member function of CWnd. This having said, in order to overwrite it succesfully you need to derive a class from CWnd or one of it's derivates (view/control).
Then you would, in your main program's InitInstance, create a 'new' object of your type using:
CMyDerivedCWnd* pWindow = new CMyDerivedCWnd;
When you would create the window object by calling "pWindow->Create(...)", the PreCreateWindow WILL get called by the framework.
Perhaps you have not derived from CWnd ? Perhaps you haven't overwritten your derived class's PreCreateWindow, but you just added some PreCreateWindow -function to your code ? In that case, check your function declaration. The framework will call THE PreCreateWindow of your DERIVED CLASS, and NOTHING else
Greets,
Antti Keskinen
----------------------------------------------
The definition of impossible is strictly dependant
on what we think is possible.
|
|
|
|
|
Thankx. I guess I misunderstood PreCreateWindow; I wanted to gain control before the window of my own main dialog will be constructed.
Btw, do you know
a) how to change font attributes IN an EXISTING CFont?
b) if I change the font size in OnSetFont, will that influence the size of the window and all controls?
because this is just what I wanted to achieve in PreCreateWindow.
|
|
|
|
|
Like I said, the PreCreateWindow allows you to fiddle with the create struct of the window. This structure contains info like the window class, window title, cursor, default brush, menu etc etc. This function is called before the Windows API call 'CreateEx' is called. This API call is responsible for actually creating the Windows window object. The framework will bind then this object (by it's handle) to the CWnd/CDialog object.
For example, in custom controls, it is common to make a check for class name in the PreCreateWindow -override. If this member is NULL, the control will register a new window class with AfxRegisterWndClass to make sure that it has a valid class (All top-level windows in MFC MUST have a valid class name). This way it doesn't bother the end user with this.
To get a complete idea of this, go check the Windows API reference on window objects. Look for things like WNDCLASS structure, RegisterWndClass function, CreateWindow and CreateWindowEx functions. These functions are called by the framework to actually create it's objects. You can, just as well, create them yourself and call the 'Attach' method of CWnd to bind your CWnd object to an existing window handle. Now, you can modify this window through the CWnd wrapper.
As for answers to your questions:
a) What you are trying to do is impossible, font-wise. After a Windows font object is created, you can't modify it. However, you _can_ modify a CFont object. It is just a wrapper for the underlying font.
To accomplish similar results, you can get the CFont-bound Windows font object's representation to a LOGFONT structure by calling the GetLogFont member method of CFont. This will fill the specified LOGFONT structure with the information about this specific font bound to this specific CFont.
Then, use the CFont's member function 'DestroyObject' to destroy the current font object, making sure that it is not selected to a device context, otherwise your program might crash/assert/throw an exception.
After you have destroyed the old object, modify the LOGFONT structure to meet your new demands. Then call 'CreateFontIndirect' of CFont and pass a pointer to the LOGFONT (use address-of) structure. This will create a new Windows font object with the specified parameters, and attach this font to the CFont object.
The general version of this routine (Get current params -> Destroy old -> Modify params -> Create new) is applicable to all GDI objects and their MFC wrappers (CPen, CBrush, CFont etc)
b) For some background info: each Windows window object (Window, dialog, control etc) has a default GDI object of each type bound to it. It has a default pen, a default brush... and a default font.
Now, the OnSetFont function of CDialog does precisely as it's description in MSDN says: it allows you to set a new default font for your dialog. This font is copied (passed) to all controls (statics, buttons etc) drawn by the dialog. So, yes, in a way. If you specify a new default font for your dialog, each control it draws will use this default font to draw it's texts. I am unsure whether the underlying framework routine will resize your controls depending on the font, but I believe that it will. The only way to make sure is to test it.
----------------------------------------------
The definition of impossible is strictly dependant
on what we think is possible.
|
|
|
|
|
Thanks for the explanation. However, OnSetFont receives a pointer to the CFont; it can not pass back a new CFont. I was already so far, that I displayed the current font attributes (GetLogFont) and created a new CFont - but I can't tell MFC to use this CFont.
|
|
|
|
|
Most interesting.
Apparently 'OnSetFont' didn't work as straightforward as I had understood from the MFC Reference. It seems that this handler can't be used to override the passed font object, because in doing so, the program asserts in the end. Why this happens is currently still unclear to me.
However, I've already found a few alternates, but they require you to alter the font for each and every control of your dialog box seperately. Go to your main application, and force a creation of modeless dialog box. Once the box is created, get a control ID inside it (GetDlgItem), and call this returned pointer's 'SetFont' method, issuing an address of a precreated CFont.
If a modeless dialog box is not an option, then create a dynamic CFont object in your dialog's constructor by using a LOGFONT structure with values you specify. Don't forget to zero the structure before using it. Then call 'GetDlgItem' in your dialog's WM_PAINT handler and the result's 'SetFont' to give it a new font. Remember to delete the Windows font object and release the dynamic CFont object, e.g. in your dialog class's destructor.
In all cases, remember to check your app for memory leaks, they tend to become easy with these things
-Antti Keskinen
----------------------------------------------
The definition of impossible is strictly dependant
on what we think is possible.
|
|
|
|
|
Thanks; unfortunately, this is not a solution to my problem. I did not want to complicate things with this detail, but seemingly I should have posted this: setting the fonts is not the real issue for me; I'm doing this for several controls anyway.
The "real" issue with the default font of the dialog is, that it's size determines the pixel size of the window and all controls; the x- and y-units are deducted from the average width and height of the window's font (I remember something that the y-unit is half of the font's "em-height", and the x-unit is a quarter of the character cell width).
With changing the font, I wanted to be able to change the size of everything in the dialog; I want to offer a "calibration" to the user, to adjust the window size depending on the monitor resolution and size as well as the magnification factor. See DPI (a misnomer) in Display properties", "setting", "advanced". I don't display any bit maps, just because of the distortion they cause when displayed with different settings.
Changing the font size makes Windows to recalculate everything, proportional. Any other method would work only if the program calculated not only the sizes, but the positions of the controls as well - and that's a lot of work (and it would convert the application to a dialog wizzard :^(.
I don't give it up (yet), for I find that this should be a natural way to customize an application. I find it dreadful, when an application becomes a "miniature" on a high-resolution monitor, or it "grows" out of the monitor, controls become unaccessible, etc. at low resolution.
Anyway, thanks for your effort. I'm sorry not to have started out with the precise specification of my problem.
|
|
|
|
|
I need to update data of an MFC object declared in one thread from with in an other
thread.............. This needs to be done throug handles... as described by MSDN.............
but i am not finding the required result............ can someone please make a simple Dialog Application
........... with a worker thread to update data on the Dialog....... and send it to me....
..... so that i will be in a better position to understand where i am mistaking........ i have
already wasted lot of time over this but invain...........
Ever Welcome...
|
|
|
|
|
I am trying to make a feature for one of my programs that works somewhat like the CFileDialog, however they are not close enough that I can simply derive from that class. Can someone tell me how I can find out what files and folders are in a specific folder?
Example: C:
Folder 1: Program files
Folder 2: Windows
etc.
I need to be able to do this from any place too. So if I pick "Program Files" from C:\, I then need to be able to find out what files and folders are in it...
I am sure there is some simple easy function that does this, I just can't seem to find it.
Thanks a lot!
If you have a problem with my spelling, just remember that's not my fault. I (as well as everyone else who learned to spell after 1976) blame it on Robert A. Kolpek for U.S. Patent 4,136,395.
|
|
|
|
|
|
i have a custom control that is derived from a CWnd class. I'd like to add a button to the control, but I'm not sure if i should manually draw the button in my paint method or just include a cbutton instance. what do people normally do? if i were to include a cbutton to my control, where would i actually *create* the button and place it in my control?
thanks in advance,
|
|
|
|
|
I'm a 'purist' MFC dude, so I wouldn't mix API and MFC together (CWnd with custom painted buttons (Non-CButton's))
Short explanation:
Use CButton as a static member of your CWnd-derived class. Call it's 'Create' in your derived class's WM_CREATE handler, and leave 'WS_VISIBLE' style out. Display and position the button with SetWindowPos in your WM_PAINT handler. The 'DestroyWindow' should be called automatically for all child windows when WM_DESTROY is posted to your CWnd-derived class's window object's message queue. To make sure, call it yourself in your WM_DESTROY handler.
Detailed explanation:
First, add a static member CButton m_TheButton to your class's header file, and order your constructor to call the CButton's constructor, if necessary. You can also create a CButton pointer and use 'new' to create a dynamic button. Both solutions are fine, the latter being a bit more flexible memory-wise.
Now, your constructed class contains a constructed CButton object. To create the button control, you call this member's 'Create' function, and specify the control's properties (Is child, parent is your control / Sends messages to parent etc etc). Note that when you create the button, you don't need to make it visible. See below.
A good place to call Create for the button control would be in the WM_CREATE message handler of your parent. There, you would create the button, specifying it as non-visible (leave WS_VISIBLE out). Next, go to your WM_PAINT handler, and in there use SetWindowPos to position the control to it's correct place, giving it the correct size, and making it visible. This way, the button is 'Created' only once, but if your window gets repainted, the button will remain in it's specified position and size.
Now, if you write a message handler for WM_COMMAND and make it check if the ID is the button's ID, you can handle messages caused by the user clicking on the button. As the custom control is the parent, the WM_COMMAND messages are posted to it's queue. So, overwrite WM_COMMAND handler for your custom control.
Hope this helps. If it doesn't, I can write a small app which demonstrates "a CWnd object which has a CButton child in it's middle" for you
Note that if you need to use the custom control inside a frame window (SDI Frame, for example), then you should derive it from CCtrlView instead of CWnd. CCtrlView supports all "views which have controls inside them". The Tab Window control (Window with tabs to select different views) is a perfect example of this. CCtrlView is a parent for views such as CEditView (View with Edit control) etc.
If you need, I can write an example of this also, it's good practise
Greets,
Antti Keskinen
----------------------------------------------
The definition of impossible is strictly dependant
on what we think is possible.
|
|
|
|
|
thanks for your detailed explanation. I have tried what you've described here, but it flickers alot when my control refreshes its display. i know that it's definitely the extra button on top of my existing control that's causing the flicker, and i'm not sure what to do.
CMyControl::OnPaint()
{
drawSomeStuff(); //i used Keith Rule's CMemDC in these drawing routines already
drawSomeMoreStuff();
m_button1.SetWindowsPos(&CWnd::wndTop....)
}
|
|
|
|
|
Well, I made a small miscalculation in my first reply. To explain it a bit, let's dive into the way stuff is handled in Windows.
You might already know (and if you didn't, now you do) that everything in Windows are windows. Sounds like an idiodome, but it is the fact. For example, our notorious button control is a WINDOW placed OVER a portion of parent view's area (custom control's client area).
So, you need to remake the original Create call to actually include the WS_VISIBLE style for the button. Now, after you have created the button, issue a SetWindowPos, placing the button window AFTER the control's view (first parameter to 'this'), and flagging it to SWP_HIDEWINDOW. You can ignore the size and position parameters by putting the necessary flags in the call (SWP_NOSIZE | SWP_NOMOVE, I think).
Now, when you need to show the button on your control, call it's ShowWindow with SW_SHOW flag. Note, that this call should only be made in a function which is not repeatedly called.
To clarify, consider the hiearchy we have created now. There is the custom control. It has a view. You can draw into this view (device context), displaying lines, texts, rectangles, everything you need to make it look cool. Then, you place new small window objects to represent different types of controls (Edit control, button control, hell, even a static control is a window).
This hiearchy understanding is especially relevant if you use custom-skinned windows (Common trait in custom control creation). Those could have a background image, with black rectangular holes where the controls will be. Then, they might have custom-drawn controls like bitmapped buttons, to fill those holes and fit seamlessly into the control's view.
For the code part you posted: remove the m_button1.SetWindowPos call from the WM_PAINT handler. Instead, hide it in the creation phase, and move this creation to the OnCreate-handler INSTEAD of OnCreateClient, if it is currently there.
The OnCreate-handler is called when the window representing your custom control is created. That is correct, we want to create and hide the button control when the window is being created. The OnCreateClient -handler (which is called to create the VIEW inside the window) can then display the control, if you want it to be visible as soon as the control window is shown. Remember to call the display function as the last thing in OnCreateClient, after everything else is drawn.
-Antti Keskinen
----------------------------------------------
The definition of impossible is strictly dependant
on what we think is possible.
|
|
|
|
|