|
I do not quite understand what you meant with "sending them in a blocking fashion."
SendMessage , when issued from a worker thread, does not return until the GUI thread processes the message sent. So if the GUI is stuck, SendMessage will wait forever. PostMessage , on the other hand, only leaves the message in the GUI thread message queue and returns immediately.
You were right on with OnCancel(). The way I planned to "signal the thread to die" is by using a boolean counter. OnCancel() would send a message to Doc. Doc would then set the counter to false. Meanwhile, the worker thread does its job only if counter is true.
The deadlock will happen only if OnCancel waits for the thread to actually die before returning (which is the proper way to proceed, on the other hand).
Do you mean it is advisable to *post message* instead of *send message*?
Yes. Be careful with the parameters accompanying a posted message --they mustn't be pointers to temporary variables.
Joaquín M López Muñoz
Telefónica, Investigación y Desarrollo
|
|
|
|
|
Thanks for the valuable pointers.
I did not have time to work on that problem today (busy with other programs homeworks). I will try to work on it *soon* as in tomorrow or Friday at most.
I will post an update.
Kuphryn
|
|
|
|
|
Hi there,
I have a pure win32 dialog with textboxes and static objects on it. The code is all done without MFC.
Now, the fonts seem rather huge, so I tried to modify them. I called
createfont at the beginning of my Dialog proc with various numbers
for the height variable and use various item for parameter 5. I do
as shown below:
SelectObject(hdc, CreateFont(12,2, 0, 0, FW_THIN, 0,0,0,
DEFAULT_CHARSET, OUT_CHARACTER_PRECIS, CLIP_CHARACTER_PRECIS, DEFAULT_QUALITY,DEFAULT_PITCH | FF_DONTCARE, _T("TimesNewRoman")));
and at the end of the proc, I delete it as following:
DeleteObject(SelectObject(hdc, GetStockObject(SYSTEM_FONT)));
But nothing changes. What am I doing wrong?
|
|
|
|
|
You'll want to send a WM_SETFONT message to each control, specifying the font you wish to use.
--------
Well actually they are sort of interesting Nish, on Nudes
|
|
|
|
|
Further to that, I have also created an edit control as following:
hwndEdit = CreateWindow( TEXT("edit"), tcLabel,
WS_CHILD | WS_VISIBLE | WS_BORDER | ES_LEFT | ES_AUTOHSCROLL ,
cxChar + 100, cyChar * (2 * i ) /* * (1 + 2 * i) */, 20 * cxChar + 100,
cyChar * (1.25), hwndDlg, (HMENU) i,
((LPCREATESTRUCT) lParam)->hInstance, NULL)
However, the following catch inside my dialog's WM_COMMAND catch statement, no longer works after creating my edit box :
if (HIWORD(wParam) == EN_CHANGE ||
HIWORD(wParam) == CBN_SELCHANGE)
When I click inside the text boxes, a couple of messages are generated, but they don't correspond to "EN_CHANGE". How would I find out what those messages are within VC btw? Any idea what this problem maybe?
thanks
|
|
|
|
|
In Visual Studio .net, if you add a file to a project, then that file will appear at the end of the project, rather than appearing in alphabetical order. (VS6 alphabetizes the files.) Is there a property somewhere that can be set to fix this?
|
|
|
|
|
Isn't it just that VC7 also takes into account the case of the filename? If so, this is a known bug.
source: nntp://microsoft.public.dotnet.langages.vc
IIRC it "will be fixed in a later release" but there were no promises of an sp fix (even that it would problably just adding an 'i' in the middle of a strcmp).
|
|
|
|
|
I have noticed the same thing, but if I close my project, and opens it again, the files are sorted correctly.
- Anders
Money talks, but all mine ever says is "Goodbye!"
|
|
|
|
|
OK, then this is another bug. You should probably report it to the NG I mentioned in my post.
|
|
|
|
|
I would like to learn something about virtual desktops, but it's hard to find some articles or msdn info on it.
Is there some sort of function in Windows that makes it possible to switch desktops? As far as I know windows does support it completely, so it shouldn't be hard to code.
Got any links or information?
Cheers!
|
|
|
|
|
It's not fully supported (f.ex. creating a new desktop still gets SystemParametersInfo to return the working area of a desktop with an Explorer bar), and you can't move windows from one desktop to another like you'd expect from any other OS, but you should have a look at the Win32 SDK sample "switcher". It's using CreateDesktop & co.
Note: You [obviously] need an NT kernel based OS for this.
|
|
|
|
|
Thanks for the feedback, but I was looking for something that would work on both NT and 9x.
There are quite many apps out there that work on 95/98, so it must be possible. As the apps are fairly small I guess it doesn't take an awful lot of code to make it work.
I'll keep searching, if you got an idea please tell me.
Thanks in advance
|
|
|
|
|
In Win9x it's completely unsupported. I've seen references to apps being _really_ ugly and to "switch desktop" they just grab a handle to any other apps window and move it to e.g. "appWnd.currpos - screenWidth", but I'd say yo get no friends from that approach even that it appears to work.
Now you know how some others do it. I just hope you don't do it yourself...
And even if you do, you'd have to track e.g. ALT+TAB to either not display the apps on "another desktop", or to swith desktop when alt-tabbing to an app on "another desktop".
|
|
|
|
|
Okay, thanks.
I guess I have to do it in the dirty way, as there appears to be no proper solution.
But as the desktop is a class of some sort it should be possible to create an array of them. I wonder why it isn't an array of desktops in the first place....
|
|
|
|
|
Hello there,
This isn't so much a problem (because I've got a solution for it) but I would like to know why it has happened in the first place. I've made use of a CPropertySheet control in one of my applications, it has two tabs (CPropertyPages) on it inherited from dialogues as CPropPage1 and CPropPage2 etc., pretty standard MFC via MSDN stuff. The sheet is constructed using AddPage (I think it's called that) not member variables in the CPropertySheet, everything works just perfectly, it constructs, shows and all the controls work great.
Now, when a button on the first property page is clicked, some extended processing needs to occur so I launch a worker thread and do some work. This works great too. Recently I added some options on the second property page and needed to make use of them during the extended processing thread on the first property page - still with me?
I wrote code (quickly guestimated) something like this:
void PropPage1::ButtonClick()
{
AfxBeginThread( Thread, this );
}
UINT Thread(LPVOID pParam)
{
CPropPage1 *caller = (CPropPage1 *)pParam;
CPropPage2 *options = NULL;
CPropertySheet *parent = NULL;
if(caller)
{
parent = (CPropertySheet *)GetParent();
if(parent) options = parent->GetPage(1);
... on and on - the rest doesn't matter.
}
return( preset_errorcode_from_somewhere );
}
Does that look OK? The reason I stop here is because at the "..." I get an Access Violation from CPropertySheet::GetPage(...) - the exact violation is from a CPtrArray I believe. No matter how many variations I do on this code, the same thing always happens. I might add that GetPageCount() correctly returns 2 indicating that there are two pages available.
The EXACT same code does not crash, if it is called from the CPropPage1::ButtonClick() handler instead of the worker thread. Now I'm aware that the code isn't exactly thread safe but should it really be crashing? I aren't aware of the behind the scenes operation, but obviously something is crossing a boundary somewhere. Why? My solution was to pass pointers to the PropertyPages via a structure into the thread and that works fine. The problem would seem to be a fault with the way GetPage(...) works because all of the other CPropertyPage members appear to function perfectly.
Just curious to know if anyone has a potential explanation for this behaviour?
Jon.
|
|
|
|
|
The problem is a very frequent one, and stems from the fact that CWnd -derived objects do funny things across threads. The explanation is a little long, please bear with me:
Given a Cwnd , its associated HWND handle is simply stored in the m_hWnd member. The other way around, obtaining the associated CWnd from a given HWND , is not that simple. There's no easy way to have Win32 store some pointer to the CWnd inside the data hold for a particualr HWND . To work around this problem, MFC guys decided to keep a global map of HWND s to CWnd pointers. Now comes the key point: for historical and performance reasons, this HWND to CWnd map is not unique, but instead each thread has its own, stored in so called thread local storage (TLS). In your particular case, the worker thread is given a pointer to CPropPage . So far so good. But when GetParent is called, the following sequence of events happen:- Win32
::GetParent is called, returning a valid HWND .
- The associated
CWnd is sought for, and as there is none local to this thread, a mock-up one is created (and inserted into the map). This object is not the CPropertySheet you began with. And the rest is easy. GetPage fails because it is issued on a CWnd constructed out of nothing, with no information about the original CPropertySheet (apart from being associated to the same HWND .)
Calls to methods of caller will work OK nevertheless, as this time caller is actually the real object.
The moral of this story is: don't pass CWnd pointers across threads.
Joaquín M López Muñoz
Telefónica, Investigación y Desarrollo
|
|
|
|
|
How can I make a Combo Box uneditable. ie The user will not be allowed to type characters into it, only select something from the list
|
|
|
|
|
use the CBS_DROPDOWNLIST style instead of CBS_DROPDOWN .
--------
Well actually they are sort of interesting Nish, on Nudes
|
|
|
|
|
|
Hello,
The MSDN docs don't say how to respond when the serialization tries to serialized an unsupported version (see code snippet). Any ideas?
void MyObj::Serialize(CArchive& ar)
{
if (ar.IsLoading() == TRUE) {
int nVersion = ar.GetObjectSchema();
switch (nVersion) {
case 1:
ar >> m_id;
break;
// unknown version
default:
--> WHAT TO DO HERE????
break;
}
}
else {
ar << m_id;
}
}
|
|
|
|
|
WHAT TO DO HERE????
Throw an exception?
|
|
|
|
|
MSDN doc about CArchive::Serialize features this interface:
virtual void Serialize( CArchive& ar );
throw( CMemoryException );
throw( CArchiveException );
throw( CFileException ); which means that the framework expects the method to throw any of the exceptions listed above. In your particular case, CArchiveException is the appropriate one to throw, with the m_cause member set to CArchiveException::badSchema .
Joaquín M López Muñoz
Telefónica, Investigación y Desarrollo
|
|
|
|
|
I have an application that is very memory intensive being used with other applications that are also very memory intensive. I execute the code that allocates memory in a try/catch block so that I catch any problems that may occur. The problem is that when I try to display a message box to inform the user what happened, my application crashes when MessageBox ultimately calls AfxCallWndProc with a NULL pointer. After looking in wincore.cpp, I was able to see the problem is the FromHandlePermanent call in AfxWndProc returns NULL, and AfxCallWndProc proceeds to used that NULL pointer to call WindowProc. Since the window pointer is NULL, the WindowProc call crashes my app. Is there any way around this short of try/catching all of my AfxMessageBox calls???
|
|
|
|
|
Try using a raw call to Win32 MessageBox instead.
Joaquín M López Muñoz
Telefónica, Investigación y Desarrollo
|
|
|
|
|
::MessageBox and AfxMessageBox both have the same problem.
|
|
|
|
|