|
What on earth does that have to do with the header ?
I agree - the world needs more ways to spam each other. Check out the examples here on CP, and you, too, can help spread the joy.
Christian
The tragedy of cyberspace - that so much can travel so far, and yet mean so little.
|
|
|
|
|
Christian Graus wrote:
What on earth does that have to do with the header ?
I think it was Colin Davies who once said there is nothing wrong in marketing your post using a handsome subject
Nish
It's seven o'clock
On the dot
I'm in my drop top
Cruisin' the streets - Oh yeah
I got a real pretty, pretty little thing that's waiting for me
|
|
|
|
|
I'll admit it beats 'Help needed - URGENT !!!'
Christian
The tragedy of cyberspace - that so much can travel so far, and yet mean so little.
|
|
|
|
|
ROTFLMAO
Nish
It's seven o'clock
On the dot
I'm in my drop top
Cruisin' the streets - Oh yeah
I got a real pretty, pretty little thing that's waiting for me
|
|
|
|
|
Hi Everyone,
I am trying to find some resources on dealing with the W2K/XP window focus changes. I've hit the web a few times and not found much. There's some connected repaint changes too.
An old app running in full screen relied on the NT behaviour to switch windows.
Thanks,
Davy
http://www.LateDecember.com
|
|
|
|
|
Hi,
Does anyone knows to calculate the file size with the parameters width ,height & resolution for a .jpg,.tif,.psd,.pcx file formats?
Thanks
Neha
|
|
|
|
|
Hi Neha. All of the formats you list have some compression feature, which means it is in general impossible to know how much a file will occupy without actually creating it. Also, some of the formats include some sort of "quality" parameter that controls the tradeoff between visual similarity to the original and file size.
In view of this, the best you can have is an estimation of how much the file size will be. This is a hard problem and I don't think any conclusive answer exists for the formats you're interested in. If you're only concern is preallocating some memory so that the compression algorithms will not run out of space, you can assume in general
sizecompressed <= sizeoriginal + Ksafeguard.
Values of Ksafeguard as small as 10 KB are usually enough.
Joaquín M López Muñoz
Telefónica, Investigación y Desarrollo
|
|
|
|
|
This morning I defined a user message and a handler to deal with it.But I kept getting an error under the release mode while it works well(I mean no warning) under the debug mode.
In the end I found that it only because that I forget to add parameters to the function.
LRESULT HANDLER() ---> LRESULT HANDLER(WPARAM wParam,LPARAM lParam)
But it really cost me a lot of time.
I want to know whether there are any methods to find this kind of errors that only occur under the release mode but run ok under the debug mode?
Thx ahead.
|
|
|
|
|
The way described here is very effective:
http://www.codeguru.com/debug/release_ver.shtml
|
|
|
|
|
This one is particularly hard to figure out (good job, btw) because the VC compilers up to version 6 didn't flag problems with preprocessor macros whose fn signatures are wrong.
The good news? VC 7 will catch this at compile time.
|
|
|
|
|
Why doesn't the following code work:
intDay = atoi(strTime[1].c_str);
it makes sense, that the c_str member function would convert the basic string to a char*, I get the following compile-time error:
error C2228: left of '.c_str' must have class/struct/union type
Also,
intHour = atoi(strTime.substr(2,1).c_str);
doesn't work either.
any thoughts?
tim
---------------------------------------
Tim Booher
|
|
|
|
|
c_str is a member function, not a variable, so you have to write it like this:
intDay = atoi(strTime[1].c_str<font color=#ff0000>()</font>);
Joaquín M López Muñoz
Telefónica, Investigación y Desarrollo
|
|
|
|
|
intDay = atoi(strTime.substr(1,1).c_str());
intHour = atoi(strTime.substr(2,1).c_str());
c_str is a member function of std::string (I guess strTime *is* a std::string), member fn's must be called using ()
strTime[1] returns a char, which doesn't have a c_str member function.
|
|
|
|
|
how do i convert a char
intDay = atoi(strTime[1]); obviously doesn't work . . .
Tim
---------------------------------------
Tim Booher
|
|
|
|
|
atoi(strTime.substr(1,1).c_str()) // <== substr of length 1
if you rely on ASCII encoding (which should be safe as long as you live with char's), it's
int day = strTime[i] - '0';
or - a bit more forgiving -
int day = isdigit(strTime[i])) ? strTime[i] - '0' : 0;
|
|
|
|
|
Hi all,
I am making a MFC dialog application that connects to serial devices. I'm using multiple threads and what I want to do is update status messages from the threads to a box in the dialog application. I had planned on using a rich edit combo box and then calling a function to add the message I wanted to the CString attached to the control, however it looks like this is a No-No using threads.
Any ideas or pointers to articles on how I should do stuff like this??
Thanks
-Mark
|
|
|
|
|
This approach can work if you take some precautions. In order to ensure proper concurrency in the access to the dialog box from the different threads, use SendMessage . so, instead of having a regular method CMyDlgBox::AddString(const CString& str) , set a user-defined message (say WM_MYDLGBOX_ADDSTRING ), write a handler for it and have the threads feed the message box with m_myDlgBox.SendMessage(WM_MYDLGBOX_ADDSTRING,...) . The other safety measure you should take is making sure that the dialog box does not lock on the worker threads (say by doing WaitForSingleObject on them): this could result in deadlocks if the threads are blocked on the previous SendMessage .
Joaquín M López Muñoz
Telefónica, Investigación y Desarrollo
|
|
|
|
|
Either use the way specified by the other reply, or:
pass the HWND of the richedit control to the worker thread, and use
CRichEditCtrl * re = (CRichEditCtrl *) CWnd::FromHWnd(hwdRichEdit);
_ASSERTE(re && re->IsKindof(RUNTIME_CLASS(CRichEditCtrl));
|
|
|
|
|
Yeah, but then he'd need sync mechanisms too.
If you send messages you dont need any sync mechanisms.
Nish
It's seven o'clock
On the dot
I'm in my drop top
Cruisin' the streets - Oh yeah
I got a real pretty, pretty little thing that's waiting for me
|
|
|
|
|
All the InsertText etc. are SendMessages - which do the job nicely.
MFC's thread support is intended to work this way (although this can be quite a pain)
|
|
|
|
|
Mr. Lopez has the best answer. Passing messages from a thread to a window (which is running on the main app thread) is the best way for these objects to communicate.
But here are some more things to think about...
PostMessage is a better choice than SendMessage. SendMessage waits for a response from the receiver. This can cause deadlocks. Also PostMessage is the only way to send a message to a user thread.
Note that using PostMessage requires a little more work. You can't do this:
CString s("Thread is busy.");
::PostMessage(hWnd, WM_UPDATE_STATUS, (WPARAM)0, (LPARAM)&s); If s loses scope before the message get processed then your code will crash. You will want to do this:
CString *ps = new CString("Thread is busy.");
::PostMessage(hWnd, WM_UPDATE_STATUS, (WPARAM)0, (LPARAM)s); As noted the receiver must delete the object so you don't have a memory leak:
LRESULT CMyWnd::OnThreadMessage(WPARAM w, LPARAM l)
{
ASSERT(l);
if(l)
{
CString *ps = (CString *)l;
delete ps;
}
return 0;
} You can see this requires more work but the code is much more crash proof.
Your threads should also check their message queues. This gives your window a way to communicate to them. This gives you a chance to tell them to stop or die. You can do something like this in your thread loop:
MSG msg;
if(::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
if(msg.message == WM_STOP_THREAD)
{
}
else
if(msg.message == WM_QUIT)
{
}
} When you are done with the threads make sure they die and clean up. I do something like this before my window closes:
void CMyWnd::OnDestroy()
{
if(m_pThread)
{
m_pThread->PostThreadMessage(WM_QUIT, 0, 0);
WaitForSingleObject(m_pThread->m_hThread, INFINITE);
delete m_pThread;
m_pThread = NULL;
MSG msg;
while(::PeekMessage(&msg, (HWND)NULL, WM_UPDATE_STATUS,
WM_UPDATE_STATUS, PM_REMOVE))
{
CString *ps = (CString *)msg.lParam;
if(ps)
delete ps;
}
}
CView::OnDestroy();
} Keeping these things in mind when you write thread code will help keep your threads robust and crash proof.
Hope this helps.
Jonathan Craig
www.mcw-tech.com
|
|
|
|
|
Thanks for your replies everyone! Its given me something to work on.
I'm very new to MFC and Windows Programming, but I'm learning a lot about it. The frustrating thing is that I know I'm getting stuck on things that would probably be quite simple!
Anyway, I think I figured out how to create a custom message and map it to a function, but what is the handle hWnd (is it the dialog handle or the Richedit control handle?) and how should I get it and access it from the thread?? This is probably a silly question though and I'll probably figure it out before long
Thanks again
-Mark
|
|
|
|
|
No, that's not a silly question. After I posted my message I noticed I left that information out.
hWnd is a HWND type variable which is a standard windows handle. If you have any class derived from CWnd (dialogs, controls, views, etc.) they have a windows handle. It is the m_hWnd member variable. The CWnd::GetSafeHwnd() method is the best way to get it. See the MSDN.
If your thread is going to send or post a message back to a window, then it must have at least a HWND to the window. You could pass it a pointer to the window object itself like CDialog *, CView *, CFormView *. Since each of these are derived from CWnd they all have a m_hWnd member. I prefer to pass the thread just the m_hWnd (HWND) member since that's all it needs to send or post a message. Also the thread doesn't need to know what type of window (dialog, view, etc.) it is, just that it is a window. This make the thread code a little more reusable.
You can pass a thread any information it needs from the AfxBeginThread method. The second parameter is used for this. I like to pack the information into a structure and pass a pointer to the structure.
In the header file:
#define WM_THREAD_WORKING (WM_USER + 1)
typedef struct _thread_info_tag
{
HWND pNotifyWnd;
long lValue1;
int nValue2;
char szValue3[80];
} _thread_info;
class CMyDialog : public CDialog
{
.
.
static UINT ThreadFunc(LPVOID lpParam);
.
.
.
.
afx_msg LRESULT OnThreadMessge(WPARAM wParam, LPARAM lParam);
DECLARE_MESSAGE_MAP()
}; In source file:
BEGIN_MESSAGE_MAP(CMyDialog, CDialog)
.
.
ON_MESSAGE(WM_THREAD_WORKING, OnThreadMessge)
END_MESSAGE_MAP()
CMyDialog::OnStartThread()
{
_thread_info *pInfo = new _thread_info;
pInfo->pNotifyWnd = this->GetSafeHwnd();
pInfo->lValue1 = 12345;
pInfo->nValue2 = -321;
strcpy(pInfo->szValue3, "String for thread.");
AfxBeginThread(ThreadFunc, (LPVOID)pInfo);
.
.
}
UINT CMyDialog::ThreadFunc(LPVOID lpParam)
{
ASSERT(lpParam);
_thread_info *pInfo = (_thread_info *)lpParam;
HWND pNotifyWnd = pInfo->pNotifyWnd;
long lValue1 = pInfo->lValue1;
int nValue2 = pInfo->nValue2;
char szValue3[80];
strcpy(szValue3, pInfo->szValue3);
delete pInfo;
.
.
::PostMessage(pNotifyWnd, WM_THREAD_WORKING, 0, 0);
.
.
}
LRESULT CMyDialog::OnThreadMessge(WPARAM wParam, LPARAM lParam)
{
.
.
return 0;
} That's how it's done...
Hope this helps.
Jonathan Craig
www.mcw-tech.com
|
|
|
|
|
Thanks Jonathan, really appreciate the help!
I had a bit of a lightbulb moment yesterday where it all clicked and started making a bit of sense!
I found out that by casting (LPVOID)this and passing it to my thread, I could access the m_hWnd member of the object that started the thread and post the message like that.
I knew that was probably not the best or safest way to do it either, and my custom event message isnt as neat as yours so that's a great help!
Thanks again!
-Mark
|
|
|
|
|
Just one Quick Question about PostMessage though . . .
What's the difference between WPARAM and the LPARAM?? I see they are both 32bit message parameters, but cant see any significant difference? Are there any restrictions on the use of either of them?
Thanks
-Mark
|
|
|
|