|
Thanks Dave, Will look into the Message Pump,
The Thread lesson looks good.
|
|
|
|
|
Sticking just to threads:
Go to the basics, the Windows API first. The problem with classes is that they help you but you have to do it the way the class author wanted it done. That doesn't help you learn threads, only gives you some magic to make it work. Personally I hate magic and need to see behind the curtain.
All you need to start is one function,
long thread_id;
HANDLE h = _beginthreadex(NULL, 0, ActuallyGetStats, NULL, 0, (unsigned *)&thread_id);
and some code with the proper calling conventions
unsigned int __stdcall ActuallyGetStats(void *)
{
return ERROR_SUCCESS;
}
This will run as a separate thread. You can put some code in there to, let say, loop 10 times, sleeping for 10 seconds each time and printing / TRACE() a message saying "I'm alive". You can also set breakpoints in there.
Now you can do some tests on the returned HANDLE in the main code to see if it's done or you can do other things. In my case, that _beginthreadex() call is done when a button is pushed on the GUI, kind of like what you had in mind.
You can also pass parameters to the function that it can use to get pointers to objects that might tell it what to do. That would be in the 4th parameter, which I've set to NULL here because there are no arguments needed.
Anyway, this is the basic start of a thread. It might be easier to play with than figuring out somebody's conventions in a class.
|
|
|
|
|
I must concur on your standing of using other peoples code. That has always gotten me into trouble in the past and the present. That's why I wrote my own IBindCallbackStatus, and did not use the example code, and I fully understand how my code works - The WCHAR issue a couple of days ago.
I'll start 1 statement at a time, and build it up, and look into that message pump that Dave mentioned.
Oh, 1 question, at what point should I start the thread, at button click, or inside the function that is called with button click?
Button Click "Next"
call function - "Prepare" - adjust buttons and artwork, setup progress bar, setup cancel button, check previous
call function - "download" - Start bind callback - start URLFileDownload
Return to window
Thanks Chunk.
|
|
|
|
|
I start the thread in the processing of the button click, in the routine pointed to by ON_BN_CLICKED() entry in the message map.
Where you start yours is up to you but I like to keep the functions of the GUI in the GUI so if you have some "pretty up" work to do, I say do that in the GUI module and then fire up the thread to do the work.
As for the Message Pump, really, I don't think you need to look into that. Basically if the GUI thread is working normally, not freezing while you are doing other processing, etc then it is already using its own message pump and should you should *not* do one yourself. If you move the long running processes into another thread, then the GUI thread should remain responsive.
An alternative message pump is only necessary when you jam all sorts of processing into your message processing routines, like if you tried to do the download inside the routines called when the button was clicked. And, there are folks out there who will say that providing your own message pumps is a hack and should never be done (and you know who you are ) so I'd say hold off discussion on message pumps until you are in the mood to deal with the purists (for the record, I am not one and I do use message pumps when necessary, and no, they are not a hack )
|
|
|
|
|
I understand that other's code can be more confusing than helpful at times, with this in mind I'll present this simple example in the hope it's not confusing.
I've just created the most simple dialog app I can. There's a single dialog with a test button and a quit button. Hitting the test button starts 10 threads, each with a different timeout value. Upon timeout, the thread sends a message to the main window which then sounds a message beep.
Hope it's of use..
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <process.h>
#include "resource.h"
#include <stdio.h>
#define WM_THREAD_COMPLETE WM_USER+1
typedef void (*voidFuncPtr)(void*);
typedef struct
{
int delayMs;
int myThreadId;
voidFuncPtr callbackFunc;
long winThreadId;
uintptr_t handle;
} threadHeader_t;
HINSTANCE hInst;
HWND mainDlgHwnd;
threadHeader_t threadList[10];
unsigned int __stdcall myThreadFunc(void *data)
{
threadHeader_t *header;
header = (threadHeader_t *)data;
printf("In thread func %d, delay %dMs\n", header->myThreadId, header->delayMs);
Sleep(header->delayMs);
if (header->callbackFunc)
header->callbackFunc(header);
return ERROR_SUCCESS;
}
void myCompletionCallback(void *data)
{
threadHeader_t *header;
header = (threadHeader_t *)data;
PostMessage(mainDlgHwnd, WM_THREAD_COMPLETE, header->myThreadId, 0);
}
void onTestBtn()
{
int i;
for (i=0; i<10; i++)
{
threadList[i].callbackFunc = myCompletionCallback;
threadList[i].delayMs = (10-i)*1000;
threadList[i].myThreadId = i;
threadList[i].handle = _beginthreadex(NULL, 0, myThreadFunc, &threadList[i], 0, (unsigned *)&threadList[i].winThreadId);
}
}
BOOL CALLBACK DialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch(uMsg)
{
case WM_INITDIALOG:
mainDlgHwnd = hwndDlg;
return TRUE;
case WM_CLOSE:
EndDialog(hwndDlg, 0);
return TRUE;
case WM_THREAD_COMPLETE:
MessageBeep(MB_OK);
return true;
case WM_COMMAND:
switch(LOWORD(wParam))
{
case IDC_BTN_TEST:
onTestBtn();
return TRUE;
case IDC_BTN_QUIT:
EndDialog(hwndDlg, 0);
return TRUE;
}
}
return FALSE;
}
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
hInst = hInstance;
return DialogBox(hInstance, MAKEINTRESOURCE(DLG_MAIN), NULL, (DLGPROC)DialogProc);
}
|
|
|
|
|
An excellent sample, I may well have a use for it.
Unrequited desire is character building. OriginalGriff
I'm sitting here giving you a standing ovation - Len Goodman
|
|
|
|
|
I still use beginthread() and beghinthreadex() alot, but have used CWinThread with MFC apps, it is pretty simple to use: http://msdn.microsoft.com/en-us/library/48xz4yz9(v=vs.80).aspx[^]
From a thread you can post progress info or completion info back to your main windows message handler specifying a WM_USER+xxx value (ie, a custom message).
==============================
Nothing to say.
|
|
|
|
|
That's food for thought.
I 'm not really sure what MFC is. I think it's a c++ with more pre-written wrappers, and puts in closer to vb or c-sharp in terms of ease of use.
I opted for the win32 to get a real feel for programming at a low level, and would prefer to stay away from MFC for a few more months. That way I'll have a better understanding of VB, CS, and MFC in the future.
I gonna work on exiting the thread today, in the normal state, and try to work out some sort of per-staging for canceling the loop, and exiting the thread. Then I just have to figure out the messaging.
Once I get this working, I'll try a dialog box with multiple downloads and threads, that gets all the pre-requisties for the program at once.
|
|
|
|
|
jkirkerx wrote: I 'm not really sure what MFC is
MFC is a set of classes writtn in C++ that wrap the WIn32 API.
I like it. It is easy to use, quick to develope, and effective.
If you are using the win32 api then just use the beginthread() func.
==============================
Nothing to say.
|
|
|
|
|
Does it make real windows programs?.
I wrote a one click app in vb, and it's a pain in the a** to maintain and deploy. The program I'm writing now is to replace the vb program I wrote. The program below. It's so hard to package and deploy that program, that it's not worth the effort.
http://www.ice5commerce.com/Applications/suWizard_2012/SetupWizard.html[^]
I made a huge mistake in the program, in which I tried to make it support XP and Vista, and it bombs on XP because I could not deploy the Microsoft.Web.admin.dll to XP. I had to rely on the web server dll to get the path to the website, so I can find the AppData Folder.
|
|
|
|
|
jkirkerx wrote: Does it make real windows programs?.
Of course.
I would suggest using MFC, but, you need to go through one of the MSDN tutorials first, it can be a little complex at first to get to know the tools.
==============================
Nothing to say.
|
|
|
|
|
I just don't want to load that c++ redistribute program
|
|
|
|
|
Yeah, OK. Since you are learning then stick with the win32 api and c++, it wil give you a great foundation to make MFC code rerally fly later on.
==============================
Nothing to say.
|
|
|
|
|
I'm working on Win7 and VC++2010. I've built MFC application with Web Browser Control I added registry entry to enable the "Open in new Tab" but I need to disable/invisible the "Open in new Window".
Anyone knows how to do this?
10x
Dan
Dan B.
|
|
|
|
|
Hi,
I'm trying to create a Windows application that needs to do the following:
-The application is comprised of only one dialog window that will render a bitmap.
-I would like this bitmap to be a screen capture of exactly what lies behind my window. If I were to move the app window, the bitmap content would update according to what new content is behind it. In some sense the window would look like a hollow frame, although the content inside it would be altered somewhat.
I know that there are transparent window API's, and while that would let me "see" what lies behind, it wouldn't actually provide the copy of the pixels that I need to manipulate.
I'm pretty sure have that Windows keeps track of the non-active desktop space, including what lies behind the active window. Does anyone know of an API call or a method that would allow me to get at this?
Anyone's help is appreciated. Thanks!
|
|
|
|
|
Quite a few articles here[^] on CodeProject.
Unrequited desire is character building. OriginalGriff
I'm sitting here giving you a standing ovation - Len Goodman
|
|
|
|
|
When you want to do the screen shot, do the following steps:
- minimize your window
- wait shortly (other windows will now be re-painted)
- do the screen shot of the whole screen
- restore your window
- get the (screen) position and size of your window and cut the corresponding region from your screen shot. That's now the region of interest.
|
|
|
|
|
All you need is the handle of the window and PrintWindow .
void CScreenShotDlg::OnPaint()
{
CPaintDC dc(this);
HWND hWnd = ::FindWindow( 0, _T( "myWindow" ));
PrintWindow( hWnd,
dc.GetSafeHdc(),
0 );
}
This [ article ] shows how to capture a window even if it is minimized or fully hidden by other windows
The [ PrintWindow ] function (MSDN).
|
|
|
|
|
That's great! Thanks a lot for your help, and I'll let you know how things go.
|
|
|
|
|
This is my first post so please be kind.
I have a project that requires the locale for the current session to be set to something different than the system setting, e.g. system is American English but the session needs to be German. The program uses setlocal.c aand related routines installed with VS2005.
This works well for most languages. The problem is that some locales/languages cannot be set with this method per MS (
|
|
|
|
|
CliffRat wrote: The problem is that some locales/languages cannot be set with this method per MS
If this is a published restriction I am not sure what you expect from this site.
Unrequited desire is character building. OriginalGriff
I'm sitting here giving you a standing ovation - Len Goodman
|
|
|
|
|
Silly me...
Iguess I thought someone might know of another method or possibly a workaround to this one.
|
|
|
|
|
The [setlocale] function.
The code below sets the current locale to "Germany".
#include <stdio.h>
#include <locale.h>
#include <time.h>
int main(void)
{
time_t ltime;
struct tm *thetime;
unsigned char str[100];
setlocale(LC_ALL, "German");
time (<ime);
thetime = gmtime(<ime);
if (!strftime((char *)str, 100, "%#x",
(const struct tm *)thetime))
printf("strftime failed!\n");
else
printf("In German locale, strftime returns '%s'\n",
str);
setlocale(LC_ALL, "C");
time (<ime);
thetime = gmtime(<ime);
if (!strftime((char *)str, 100, "%#x",
(const struct tm *)thetime))
printf("strftime failed!\n");
else
printf("In 'C' locale, strftime returns '%s'\n",
str);
}
|
|
|
|
|
Thanks for the suggestion but that is what is currently being used.
The problem is that some languages, and the codes are clearly documented, have a codepage value of 0 (zero). Some of these languages need to be set for the session but are rejected because a zero codepage is not handled in the code.
I need a workaround to programmatically change to these 0 (zero) codepage languages.
HELP!
|
|
|
|
|
CliffRat wrote: The problem is that some locales/languages cannot be set with this method per MS (
You could implement your own solution of course.
Or just refuse to support those, perhaps by examining the requirement that stated they were needed in the first place. Specifically what is the realistic, not imagined, market share possible from those locations in the next year? Or the next five?
|
|
|
|
|