|
Several issues:
int MailIt (char *mailserver, char *emailto, char *emailfrom,char *emailsubject, char *emailmessage)
{
SOCKET sockfd;
WSADATA wsaData;
int bytes_sent;
int err;
struct hostent *host;
struct sockaddr_in dest_addr;
char line[100000];
char Rec_Buf[301];
if (WSAStartup(0x202,&wsaData) == SOCKET_ERROR)
{
WSACleanup();
return -1;
}
if ( (host=gethostbyname(mailserver)) == NULL)
{
perror("gethostbyname");
return 1;
}
memset(&dest_addr,0,sizeof(dest_addr));
memcpy(&(dest_addr.sin_addr),host->h_addr,host->h_length);
dest_addr.sin_family= host->h_addrtype;
dest_addr.sin_port= htons(25);
if ((sockfd=socket(AF_INET,SOCK_STREAM,0)) < 0)
{
perror("socket");
return 1;
}
if (connect(sockfd, (struct sockaddr *)&dest_addr,sizeof(dest_addr)) == -1)
{
perror("connect");
return 1;
}
strcpy(line,"HELO me.somepalace.com\r\n");
bytes_sent=send(sockfd,line,strlen(line),0);
err=recv(sockfd,Rec_Buf,sizeof(Rec_Buf),0);
Rec_Buf[err] = '\0';
strcpy(line,"MAIL FROM: <");
strncat(line,emailfrom,strlen(emailfrom));
strncat(line,">\r\n",3);
bytes_sent=send(sockfd,line,strlen(line),0);
err=recv(sockfd,Rec_Buf,sizeof(Rec_Buf),0);
Rec_Buf[err] = '\0';
strcpy(line,"RCPT TO: <");
strncat(line,emailto,strlen(emailto));
strncat(line,">\r\n",3);
bytes_sent=send(sockfd,line,strlen(line),0);
err=recv(sockfd,Rec_Buf,sizeof(Rec_Buf),0);
Rec_Buf[err] = '\0';
strcpy(line,"DATA\r\n");
bytes_sent=send(sockfd,line,strlen(line),0);
err=recv(sockfd,Rec_Buf,sizeof(Rec_Buf),0);
Rec_Buf[err] = '\0';
strcpy(line,"To: ");
strcat(line,emailto);
strcat(line,"\r\n");
strcat(line,"From: ");
strcat(line,emailfrom);
strcat(line,"\r\n");
strcat(line,"Subject: ");
strcat(line,emailsubject);
strcat(line,"\r\n\r\n");
strcat(line,emailmessage);
strcat(line,"\r\n.\r\n");
bytes_sent=send(sockfd,line,strlen(line),0);
err=recv(sockfd,Rec_Buf,sizeof(Rec_Buf),0);
Rec_Buf[err] = '\0';
strcpy(line,"QUIT\r\n");
bytes_sent=send(sockfd,line,strlen(line),0);
err=recv(sockfd,Rec_Buf,sizeof(Rec_Buf),0);
Rec_Buf[err] = '\0';
closesocket(sockfd);
WSACleanup();
return 0;
} No calls to Sleep() are necessary. CRLF should both be sent, not just LF . The initial call to recv() is not necessary. After the subject, an extra CRLF pair is required. The five variables of MailIt() should be made const ant so that they are not accidently messed with.
"Approved Workmen Are Not Ashamed" - 2 Timothy 2:15
"Judge not by the eye but by the heart." - Native American Proverb
|
|
|
|
|
Is there a way to force an app to paint a window, and to Stall any further code from processing until painting is completed. Even CWnd::RedrawWindow() which appears to fit the bill according to the documentation, sometimes returns before painting is completed.
LateNightsInNewry
|
|
|
|
|
Check out CWnd::Invalidate()/::InvalidateRect() and CWnd::UpdateWindow(). Used in combination
they force an immediate WM_PAINT message.
Mark
-- modified at 19:59 Monday 19th February, 2007
BOLD texted the important words of my reply
Do you know what it's like to fall in the mud and get kicked... in the head... with an iron boot?
Of course you don't, no one does. It never happens. It's a dumb question... skip it.
|
|
|
|
|
Nope, it appears to POST these messages, and the functions return before the painting is completed.
LateNightsInNewry
|
|
|
|
|
LateNightsInNewry wrote: Nope, it appears to POST these messages
I respectfully disagree
I use this combination all the time and it paints instantly (as documented):
Invalidate(TRUE/FALSE);
UpdateWindow();
That's for entire window - you can, of course, invalidate a portion of a Window using a rect or
region.
Mark
"Do you know what it's like to fall in the mud and get kicked... in the head... with an iron boot?
Of course you don't, no one does. It never happens. It's a dumb question... skip it."
|
|
|
|
|
Hi Mark,
Thanks for your Interest. This is an issue that has caused bother for the last five years. I am trying to handle it head on now, without re-designing five years of code.
As an example, I have a Dialog Based App, which has a Maximised Window displaying a BMP as background. Message Handlers for the Dlg are typically as follows:-
void MyDialog::OnButton(){
.
.
.
COtherDlg Dlg;
ShowWindow(SW_HIDE);
LRESULT lRes=Dlg.DoModal();
ShowWindow(SW_SHOWNORMAL);
if(lRes==....
.
.
.
}
BOOL COtherDlg::OnInitDialog(){
CDialog::OnInitDialog();
DoSomethingVerryLengthy()
.
.
.
return TRUE;
}
The ShowWindow(SW_HIDE) causes the Entire App to disapear off the horizon, showing an Excell Worksheet, or whatever else is running one level lower on the Windows Stack. No Amount of UpdateWindow() InvalidateXXX() etc has got around this, I Keep seeing Excell for the Duration of
DoSomethingVerryLengthy().
Ofcourse, One solution is running things on Workerthreads, use Progress boxes, etc. Can be done, but I feel the overhead of this is unjustified if I can just find a way for the app to keep on filling the screen without showing Excell.
By the way, Tried your suggestion, by macroing in as follows:-
#define ShowWindow(X) ShowWindow(X);PaintMainWnd(X)
void PaintMainWnd(int SwType){
if(SwType!=SW_HIDE)return;
CWnd* pWnd=AfxGetMainWnd();
if(pWnd){
pWnd->InvalidateRect(NULL);
pWnd->UpdateWindow();
}
}
Still Seeing Excell, or in this case, the IDE
// By the way, Modified 1st because seems to give a smiley face
//
// By the way, Modified 2nd to Re-assure that AfxGetMainWnd()
// Actually returns a Pointer to the Background Window.
// It's Paint Method is actually Called!
// in practice the screen is not actually painted.
// The thread appears to get blocked before the physical
// painting takes place. That's why I asked for a way
// to ensure that all physical painting takes place
// before I use the thread for 'DoSomethingVerryLengthy()'
Regards
-- modified at 21:25 Monday 19th February, 2007
LateNightsInNewry
-- modified at 21:49 Monday 19th February, 2007
|
|
|
|
|
Check out GetQueueStatus(QS_PAINT)
while (GetQueueStatus(QS_PAINT))
{
AfxGetApp()->PumpMessage();
}
You may be right I may be crazy -- Billy Joel --
Within you lies the power for good, use it!!!
|
|
|
|
|
Hi PJ
Just Tried this,
No Avail.
The Problem appears to be in the Kernal, it appears to receive the Paint messages, but only actually paint the screen in it's own good time.
LateNightsInNewry
|
|
|
|
|
LateNightsInNewry wrote: The ShowWindow(SW_HIDE) causes the Entire App to disapear off the horizon
Of course it does. This is what you wanted, right? If you hide the main window then all the
children get hidden too.
DoSomethingVerryLengthy() is in OnInitDialog()?
If so, that won't work well...there's still a bunch of messages that need to be processed before
the window displays - a few WM_SIZEs, etc. then finally a WM_PAINT. If you want the window
comletely initialized and displayed BEFORE DoSomethingVerryLengthy() then maybe post a message to
yourself from OnInitDialog() and in response to that message then DoSomethingVerryLengthy().
No extra threads should be necessary here, a least for the UI - this isn't even real-time screen
updating - just simple window updates.
Putting DoSomethingVerryLengthy() on a separate thread is an option tough.
Remember that if DoSomethingVerryLengthy() is running on COtherDlg's UI thread then you need
to pump messages periodically if you expect the dialog to stay responsive.
Hope that made sense I'm still not caffeinated this morning!
Mark
"Do you know what it's like to fall in the mud and get kicked... in the head... with an iron boot?
Of course you don't, no one does. It never happens. It's a dumb question... skip it."
|
|
|
|
|
Mark Salsbery wrote: DoSomethingVerryLengthy() is in OnInitDialog()?
Mark Salsbery wrote: Of course it does. This is what you wanted, right? If you hide the main window then all the
children get hidden too.
Hi Mark,
Thanks, Also see my other reply.
That's the Nub of the problem, I am calling ShowWindow(SW_HIDE) from a Child Window, NOT the Main Window The Main Window was separately created on the heap, and just displays a bitmap to act as background.
What I want to keep displayed is the Background Bitmap Window, which appears to get clobbered for no good reason. The Question is, to stop it getting clobbered, or, to repaint it before any shenanigans in OnInitDialog();
DoSomethingVerryLengthy() is in OnInitDialog()?
It is fully acceptable and desirable that the Dialog being initialised is not displayed untill OnInitDialog() terminates. (have NO Usefull data to display untill DoSomethingVerryLengthy() completes).
I am NOT worried about displaying this one until much later, i.e. After DoSomethingVerryLengthy() has completed.
The Problem is the Disappearance of the Background window.
Thanks for your comments sofar, they have been helpfull.
regards,
LateNightsInNewry
|
|
|
|
|
Thanks to your extended description of what you have going on I think this post is outdated
(see my other reply minutes ago).
There's still a concern if DoSomethingVerryLengthy() doesn't do anything UI related. If that's
the case then there's definitely a problem having it in OnInitDialog(). Actually, until you
return from OnInitDialog() the UI isn't going to refresh.
Where does DoSomethingVerryLengthy() fit in to your latest detailed post (which window class)?
Mark
"Do you know what it's like to fall in the mud and get kicked... in the head... with an iron boot?
Of course you don't, no one does. It never happens. It's a dumb question... skip it."
|
|
|
|
|
Also...
The point I'm trying to make is that OnInitDialog is just called in response to one of the many
messages that get sent to a window during creation before the window is displayed. Trying to
do any UI updating in there won't work well Therefore, it works best to let the window be
entirely created and displayed before doing something else, especially something lengthy.
An alternative to posting yourself a message in OnInitDialog() is to start the
DoSomethingVerryLengthy() externally (via a method call) from the window that created the dialog.
I mean something like:
pOtherDlg = new COtherDlg(...);
pOtherDlg->Create(...);
//** Optional if pOtherDlg not created with WS_VISIBLE style **
pOtherDlg->ShowWindow(SW_SHOW);
pOtherDlg->UpdateWindow();
//** End Optional if pOtherDlg not created with WS_VISIBLE style **
pOtherDlg->DoSomethingVerryLengthy();
Come on, caffeine
Cheers!
Mark
"Do you know what it's like to fall in the mud and get kicked... in the head... with an iron boot?
Of course you don't, no one does. It never happens. It's a dumb question... skip it."
|
|
|
|
|
Hi Mark,
I've read your advice, and there are several points of which I want to take on board. However, I also think that a number of issues are not clear, mainly through me not explaining propperly, so here we go:-
The Application is based on a Dialog Based MFC Wizzard Application, with the following modifications:
By default,the MFC Wizzard initializes m_pMainWnd with &MyAppDlg in
CMyApp::InitInstance(). This Code was Changed as follows:
m_pMainWnd = new CBckGndWnd();
((CMainWnd*)m_pMainWnd)->DisplayBitMap("SalesCounter.bmp");
m_pMainWnd->ShowWindow(SW_SHOWMAXIMIZED );
m_pMainWnd->UpdateWindow();
This Window is intended to stay on the screen until the App Dies. Multiple Apps open on the screen is something this app tries to avoid. All Apps in this suite are designed to run on Full Screen only. People using my stuff are sales operatives, no computer literacy is assumed, They are at All times shown a Clear and Well defined Full Screen Interface. One place where you may see such thing is on a Supermarket Check-out.
It is this CBckGndWnd Bitmap window that I want to remain displayed as background to the app at all times. This window's code appears to work, and displays the Full Screen Bitmap as advertised, most of the time.
By the way this window has NO other task, other than to show on the display.
After starting this BitmapWindow on the heap, InitInstance() does some more initialisation, and hits the function:
RunCounterProcess();
This 'RunCounterProcess' Function is an Endless Loop which Starts with displaying a Dialog Box, 'CStartTransactionDlg'.
This DialogBox has an Edit Control and various buttons, each to pick an Option. The Standard response would be to enter a Customer ID Number into the Edit Control,
Sofar Sogood, No Problems.
Now After Doing this, the Girl clicks the Button 'FindCustomer', and Control passes to the handler: 'CStartTransactionDlg::OnFindCustomer()'
OnFindCustomer() does some validation and initialisation, and calls in turn something like this:-
ShowWindow(SW_HIDE);// Hides CStartTransactionDlg
CCustomerAccountDlg Dlg(pCurrentCustomer,FLAG_SHOWACCOUNT|FLAG_ALLOWPAYMENT);
Dlg.DoModal();
ShowWindow(SW_SHOWNORMAL);// Show CStartTransactionDlg
Note That ON THIS OCCASION 'ShowWindow(SW_HIDE)' is called from 'CStartTransactionDlg', WHICH IS NOT THE MAIN WINDOW!!!, But Rather, This Dialog Box is displayed ON TOP OF the Main Window.(i.e. the Bitmap!)
The Problem is, that ShowWindow(SW_HIDE) does not only seem to affect the CStartTransactionDlg from where it was called,and which we intend to hide, but also hides momentarily an unintended window, the CBckGndWnd() m_pMainWnd. To Reiterate, the instance of CStartTransactionDlg, which we hide, is NOT the Application's main window, the instance of CBckGndWnd is!!
This is fine, and works well albeit with some anoying flashing, if the instance of CCustomerAccountDlg initialises quickly. If that is slow, the app, i.e. the background bitmap disappears off the screen for more or less the duration of CCustomerAccountDlg::InitDialog(). In other words, No messages can be processed by the Procedure for 'CBckGndWnd' whilst CCustomerAccountDlg is processing WM_INITDIALOG. This is not surprising, afterall there is only one thread.
I can Only see two ways of attack:-
-Stop ShowWindow(SW_HIDE) from interfering with the Background Window
-Force the Background Window to complete Re-paint, before we start the Next Dialog
So, to recap:
What I am realy looking for is something like:
MagicFuncToStopInterferenceWithBackground();
ShowWindow(SW_HIDE);// Hides CStartTransactionDlg
MagicCodeToRepaintCBckGndWndIfAboveFails();
// And Now, on a Full Background:-
CCustomerAccountDlg Dlg(pCurrentCustomer,FLAG_SHOWACCOUNT|FLAG_ALLOWPAYMENT);
Dlg.DoModal();
ShowWindow(SW_SHOWNORMAL);// Show CStartTransactionDlg
The sad point is that the above software was written some five years age. A new version is due for 2008, which fundamentally avoids the above pitfalls. It is also a problem which only became noticable some time ago, when the database had grown to such a size that search times have become non trivial. Needless to say, I am reluctant to start multythreading an app at the end of it's life cycle. At the same time, I want to do something to remove these glitches, if at all possible with reasonable efford. Beside that, I want to find out for the future what to do to avoid this sort of thing.
Sorry for the length of this, but I hope it explains what I want to achieve
Thanks,
LateNightsInNewry
|
|
|
|
|
LateNightsInNewry wrote: Sorry for the length of this, but I hope it explains what I want to achieve
Sorry you had to type all that
The key is to get all windows updated/refreshed before any lengthy process.
I'm going to assume your endless loop sits idle (using no CPU)...correct? That'll keep everything
else snappy.
You should just have to do something like this:
ShowWindow(SW_HIDE);// Hides CStartTransactionDlg
pMainWnd->UpdateWindow();
// And Now, on a Full Background:-
CCustomerAccountDlg Dlg(pCurrentCustomer,FLAG_SHOWACCOUNT|FLAG_ALLOWPAYMENT);
Dlg.DoModal();
pMainWnd->UpdateWindow(); // this one shouldn't be necessary, but WTH, it's cheap
ShowWindow(SW_SHOWNORMAL);// Show CStartTransactionDlg
Get the pMainWnd any way that's appropriate - passed in to class object instance, gobal variable,
method of ap class, etc.
The MagicFuncToStopInterferenceWithBackground() and MagicCodeToRepaintCBckGndWndIfAboveFails()
APIs won't be out until 2020 or so.
"Do you know what it's like to fall in the mud and get kicked... in the head... with an iron boot?
Of course you don't, no one does. It never happens. It's a dumb question... skip it."
|
|
|
|
|
Heh I'm trying to stay on this sub-thread...
Here's my code (adjusted from yours) from my first response:
ShowWindow(SW_HIDE);// Hides CStartTransactionDlg
pMainWnd->UpdateWindow();
// And Now, on a Full Background:-
CCustomerAccountDlg Dlg(pCurrentCustomer,FLAG_SHOWACCOUNT|FLAG_ALLOWPAYMENT);
Dlg.DoModal();
pMainWnd->UpdateWindow(); // this one shouldn't be necessary, but WTH, it's cheap
ShowWindow(SW_SHOWNORMAL);// Show CStartTransactionDlg
If that's not enough then maybe a message pump is necesasary (I do this in my real-time video
software because I want windows completely drawn before starting video....it's more pleasing to
the users)
void _PumpWaitingMessages()
{
MSG msg;
while ( ::PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE ) )
{
if ( !AfxGetApp()->PumpMessage( ) )
{
::PostQuitMessage(0);
break;
}
}
}
...
CStartTransactionDlg::OnFindCustomer()
{
ShowWindow(SW_HIDE);
pMainWnd->UpdateWindow();
_PumpWaitingMessages();
CCustomerAccountDlg Dlg(pCurrentCustomer,FLAG_SHOWACCOUNT|FLAG_ALLOWPAYMENT);
Dlg.DoModal();
pMainWnd->UpdateWindow();
ShowWindow(SW_SHOWNORMAL);
}
*EDIT* Here's where the lengthy operation in OnInitDialog() comes in.
Normally, Dlg.DoModal(); will pump messages to refresh all the thread's windows.
If you do something lengthy in CCustomerAccountDlg::OnInitDialog(), though, then you have
interrupted the dialog's creation process and all those messages stuck in the queue don't
get processed - the dialog hasn't even entered the modal loop yet.
If this is the case, then I still recommend that within CCustomerAccountDlg, you post a user-
defined message to yourself (e.g. PostMessage(WM_STARTLENGTHYPROCESS)) from the end of
OnInitDialog() and in response to that message, start the lengthy process (instead of starting
the lengthy process from OnInitDialog()).
Mark
-- modified at 20:16 Tuesday 20th February, 2007
-- modified at 20:18 Tuesday 20th February, 2007
"Do you know what it's like to fall in the mud and get kicked... in the head... with an iron boot?
Of course you don't, no one does. It never happens. It's a dumb question... skip it."
|
|
|
|
|
Hi Mark,
Tried your Suggestion, and Actually had tried that already in similar form previously some months ago, (when that did not work, desperation started to set in) It does NOT work unfortunately. I cannot send you my code for licence reasons, at the same time, I do not think that you want to wade through some 148 MByte of Source code to find the problem.
Hence I propose to write a mini DemoApp in the next few days to demonstrate the problem I'll find out a way of getting it to you, or, maybe you suggest a way how to receive it
Thanks and Regards,
LateNightsInNewry
|
|
|
|
|
A mini demo app reproducing the problem would be great
I still think the UI thread is tied up preventing paints. If the background bitmap never repaints
then something is up elsewhere.
I'll definitely take a look at it though!
Mark
"Do you know what it's like to fall in the mud and get kicked... in the head... with an iron boot?
Of course you don't, no one does. It never happens. It's a dumb question... skip it."
|
|
|
|
|
Hi Mark,
Understand all that, but it seems to be an answer to the wrong question. I am NOT trying to paint a Dialog in the middle of creation. Rather,I want to keep an Entirely Unrelated Window on the heap which acts as visual background, painted on the screen at all times. Unfortunately it gets clobbered, I try to repaint before starting something lengthy, just does not happen.
Thanks for your much appreciated comments.
Regards,
LateNightsInNewry
|
|
|
|
|
LateNightsInNewry wrote: I am NOT trying to paint a Dialog in the middle of creation. Rather,I want to keep an Entirely Unrelated Window on the heap which acts as visual background, painted on the screen at all times. Unfortunately it gets clobbered, I try to repaint before starting something lengthy, just does not happen.
Right I'm following you
All the windows on a given UI thread use the same message loop so even tieing up a child window's
creation will effect underlying parent windows messages.
In OnInitDialog() you are in the middle of handling the WM_INITDIALOG message. Until you
return from that, all the WM_PAINT (and other) messages for all the windows on the thread are
stuck in the queue.
All messages involved in redrawing the clobbered background window need to be flushed and
dispatched before entering any new lengthy operation, unless that operation is going to
periodically pump the waiting messages (and again, OnInitDialog() is a bad place for that...the
window isn't fully created and displayed yet).
Mark
"Do you know what it's like to fall in the mud and get kicked... in the head... with an iron boot?
Of course you don't, no one does. It never happens. It's a dumb question... skip it."
|
|
|
|
|
From the MFC Help Files:
Windows sends a WM_PAINT message whenever the CWnd update region is not empty and there are no other messages in the application queue for that window.
I Need the WM_PAINT Message to be sent Independent of the Message queue
LateNightsInNewry
|
|
|
|
|
BTW, from the UpdateWindow() docs:
"The function sends a WM_PAINT message directly to the window procedure of the specified window,
bypassing the application queue. If the update region is empty, no message is sent."
"Do you know what it's like to fall in the mud and get kicked... in the head... with an iron boot?
Of course you don't, no one does. It never happens. It's a dumb question... skip it."
|
|
|
|
|
Hi Mark,
Found that one too, secs after posting, but for some reason Windows does not appear to do the actual painting. See my response 3 mins ago. Suggest we return to that thread.
LateNightsInNewry
|
|
|
|
|
Hi all,
I need to create 4 MDI child windows at the start of the program for displaying 4 different pictures, please help.
regards
|
|
|
|
|
What (more specifically) is giving you trouble? When the windows are created? How the windows
are created? Are you using Doc/View architecture?
Mark
Do you know what it's like to fall in the mud and get kicked... in the head... with an iron boot?
Of course you don't, no one does. It never happens. It's a dumb question... skip it.
|
|
|
|
|
Hi Mark,
I am using Doc/View, I am just not quite familiar about the usage of CWnd::Create(), not sure where/how to use it to make 4 child windows at same time.
regards,
|
|
|
|
|