|
Reading the article now. Thanks for the help.
Chris Christian
|
|
|
|
|
You're welcome, Chris
--PerspX
"Nowadays, security guys break the Mac every single day. Every single day, they come out with a total exploit, your machine can be taken over totally. I dare anybody to do that once a month on the Windows machine." - Bill Gates
|
|
|
|
|
Hello,
I have written a program using Visual C++ (derived from CDialog) that takes in a very large file and parses the information within the file into variables. So far, no problems with that. Due to the size of the file, this takes a few minutes to complete so I added a progress bar to my dialog to show that it is processing. Once I hit the button to begin the parse, everything works fine. The progress bar begins to grow, and the file is being parsed correctly.
Here lies my problem:
If I click anywhere on the screen and cause my dialog to lose focus, the GUI of the dialog freezes and no long responds. The parse still works correctly after I have clicked on the screen. My GUI begins to respond again once the parse function has completed.
I would just like to know how to remedy this problem? Thanks.
|
|
|
|
|
This sounds like a job for a worker thread.
"A good athlete is the result of a good and worthy opponent." - David Crow
"To have a respect for ourselves guides our morals; to have deference for others governs our manners." - Laurence Sterne
|
|
|
|
|
theallmightycpd wrote: I would just like to know how to remedy this problem?
you need either a classic "message pump" or you need to put the file reading into a worker thread that posts status messages back to the UI
|
|
|
|
|
Alright, so I had a feeling I would have to implement a worker thread. My problem is that within that thread, I need to be able to update my progress bar constantly and I know that you're not supposed to touch your GUI controls from within the worker thread. I understand that the work around is to use SendMessage() or PostMessage().
My code within my worker thread looks as follows: (m_prg is my progress control)
.
.
.
CStdioFile f1;
if( !f1.Open( pFileName, CFile::modeRead ) )
{ /* error */ }
int totSize = f1.GetLength();
m_prg.SetRange32(0, totSize); <--GUI freezes here
int curSize = 0;
m_prg.SetPos(curSize);
.
.
.
What I've got so far is that every time I want to call m_prg, I need to do it through SendMessage() or PostMessage(). The thing is that I know nothing about these functions. How do I implement them? I can't seem to figure it out.
Help would be greatly appreciated. Thanks.
|
|
|
|
|
|
The CProgressCtrl methods you are using use SendMessage to send the appropriate message to the
control.
I'm not sure why this is freezing the UI where you indicate, but if you want to try PostMessage,
then use it instead of calling the CProgressCtrl method.
For example:
//m_prg.SetRange32(0, totSize);
::PostMessage(m_prg, PBM_SETRANGE32, (WPARAM) 0, (LPARAM) totSize);
Mark
Mark Salsbery
Microsoft MVP - Visual C++
"Great job team! Head back to base for debriefing and cocktails."
|
|
|
|
|
If you choose the classic message pump route, there's an example of an MFC message pump
here[^]
Mark
Mark Salsbery
Microsoft MVP - Visual C++
"Great job team! Head back to base for debriefing and cocktails."
|
|
|
|
|
Maybe if you use of progress on the timer your problem will be solve.
|
|
|
|
|
sasOpen= InternetOpen(szClassName,INTERNET_OPEN_TYPE_DIRECT,NULL,NULL,INTERNET_FLAG_ASYNC);
assConnect = InternetConnect(assOpen,"???.???.???",INTERNET_INVALID_PORT_NUMBER,"sdfgdgdfg","dfgdgdfg",INTERNET_SERVICE_FTP,INTERNET_FLAG_PASSIVE,(long)NULL);
status = FtpGetCurrentDirectory(assConnect,curDir,&curdirLen);
why(GetLastError()); // this function displays the error message as string
//i get "overlapped i/o operation in progress"
i am trying to connect to my ftp server using the above code... opena nd connect are working well
but not the ftpgetcurrentdrectory...
what am i supposed to do ...
|
|
|
|
|
Since you've chosen to do the operation asynchronously, you are getting the appropriate error
because the operation hasn't completed.
For asynchronous operations you'll probably want to use InternetSetStatusCallback() and in the
callback you'll be notified when the operation completes (INTERNET_STATUS_REQUEST_COMPLETE).
Also, you probably shouldn't call GetLastError() unless there's actually an error. Not all
APIs reset the last error when they are successful.
Mark
Mark Salsbery
Microsoft MVP - Visual C++
"Great job team! Head back to base for debriefing and cocktails."
|
|
|
|
|
ah, thanks for responding so quickly. thank you. thats nice... i will work with your reply and accordingly i will go for the rest
|
|
|
|
|
void CALLBACK internetCallback( HINTERNET hInternet,
DWORD_PTR dwContext,
DWORD dwInternetStatus,
LPVOID lpvStatusInformation,
DWORD dwStatusInformationLength
);
void CALLBACK internetCallback(HINTERNET hInternet, DWORD_PTR dwContext, DWORD dwInternetStatus, LPVOID lpvStatusInformation, DWORD dwStatusInformationLength)
{
msgbox("something is happening");
}
assOpen= InternetOpen(szClassName,INTERNET_OPEN_TYPE_DIRECT,NULL,NULL,INTERNET_FLAG_ASYNC);
InternetSetStatusCallback(assOpen,(INTERNET_STATUS_CALLBACK) internetCallback);
when i run the program the message dosent gets displayed...
what am i supposed to do ...
some help is needed??? will you...
|
|
|
|
|
When you call InternetConnect() you need to pass a value for the dwContext parameter.
From the docs:
"Note The callback function specified in the lpfnInternetCallback parameter will not be called
on asynchronous operations for the request handle when the dwContext parameter of HttpOpenRequest
is set to zero (INTERNET_NO_CALLBACK), or the connection handle when the dwContext handle of
InternetConnect is set to zero (INTERNET_NO_CALLBACK)."
Mark Salsbery
Microsoft MVP - Visual C++
"Thanks,I overlooked the docs."
|
|
|
|
|
wow, its working after giving the dwContext a value of 1... thank you a lot...
we will catch up later... i am working on further...
|
|
|
|
|
Here's a tip -
When using callbacks in C++, the callback needs to be a global function or a static member
function. Using C++ it's nice to encapsulate the function within a class but static member
functions can't access non-static members of the class.
This is where the dwContext comes in....you can pass a pointer to a class object then in the
callback, cast the passed context back to an object pointer. With that object pointer you now
have access to the entire class
Mark
Mark Salsbery
Microsoft MVP - Visual C++
"Thanks,I overlooked the docs."
|
|
|
|
|
i havent gone through c++ much... anyway this information i am saving for future purpose and one day i might be needing this because i am going to enhance my ftp program to a superficial one...
thank you for there tips...
|
|
|
|
|
void Ftp()
{
assOpen= InternetOpen(szClassName,INTERNET_OPEN_TYPE_PRECONFIG,NULL,NULL,INTERNET_FLAG_ASYNC);
InternetSetStatusCallback(assOpen,(INTERNET_STATUS_CALLBACK) &internetCallback);
assConnect = InternetConnect(assOpen,"???????",INTERNET_INVALID_PORT_NUMBER,"fhfhfgh","fhfghfgh",INTERNET_SERVICE_FTP,INTERNET_FLAG_PASSIVE,(long)1);
}
and i have setup a callback function and is working well...
i am callingthefunction FtpGetCurrentDirectory...
the return value is zero
no effect in the callback
and the getlasterror showed invalid handle...
what's next...
|
|
|
|
|
I wrote a program to trim a segment mpeg file to avi file, the video in the avi file is ok, but I can't output the audio into it. when I try to find out the output pin of the audio group, it returns error code:"the group does not has output pin", should I exract audio from mpeg file to a new file then add it to Timeline? please give any suggestion. my code is following:
//Video
hr = pTL->CreateEmptyNode(&pVideoGroupObj, TIMELINE_MAJOR_TYPE_GROUP);
hr = pVideoGroupObj->QueryInterface(IID_IAMTimelineGroup, (void **)&pVideoGroup);
AM_MEDIA_TYPE mtVideo;
ZeroMemory(&mtVideo, sizeof(AM_MEDIA_TYPE));
mtVideo.majortype = MEDIATYPE_Video;
mtVideo.subtype = MEDIASUBTYPE_RGB555;
mtVideo.pbFormat = (BYTE*)CoTaskMemAlloc(sizeof(VIDEOINFOHEADER));
VIDEOINFOHEADER *pVideoHeader = (VIDEOINFOHEADER*)mtVideo.pbFormat;
ZeroMemory(pVideoHeader, sizeof(VIDEOINFOHEADER));
//the m_mtSrcVideo is AM_MEDIA_TYPE info. gotten from mpeg file.
VIDEOINFOHEADER *pVideoHeader0 = (VIDEOINFOHEADER*)m_mtSrcVideo.pbFormat;
pVideoHeader->bmiHeader.biBitCount = pVideoHeader0->bmiHeader.biBitCount;
pVideoHeader->bmiHeader.biWidth = pVideoHeader0->bmiHeader.biWidth;
pVideoHeader->bmiHeader.biHeight = pVideoHeader0->bmiHeader.biHeight;
pVideoHeader->bmiHeader.biPlanes = pVideoHeader0->bmiHeader.biPlanes;
pVideoHeader->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
pVideoHeader->bmiHeader.biSizeImage = DIBSIZE(pVideoHeader->bmiHeader);
mtVideo.formattype = FORMAT_VideoInfo;
mtVideo.cbFormat = sizeof(VIDEOINFOHEADER);
mtVideo.bFixedSizeSamples = TRUE;
mtVideo.lSampleSize = DIBSIZE(pVideoHeader->bmiHeader);
hr = pVideoGroup->SetMediaType(&mtVideo);
hr = pTL->AddGroup(pVideoGroupObj);
hr = pTL->CreateEmptyNode(&pVideoTrackObj, TIMELINE_MAJOR_TYPE_TRACK);
hr = pVideoGroup->QueryInterface(IID_IAMTimelineComp, (void **)&pVideoComp);
hr = pVideoComp->VTrackInsBefore(pVideoTrackObj, 0);
hr = pVideoTrackObj->QueryInterface(IID_IAMTimelineTrack, (void **)&pVideoTrack);
hr = pTL->CreateEmptyNode(&pVideoSourceObj, TIMELINE_MAJOR_TYPE_SOURCE);
hr = pVideoSourceObj->QueryInterface(IID_IAMTimelineSrc, (void **)&pVideoSource);
//Audio
hr = pTL->CreateEmptyNode(&pAudioGroupObj, TIMELINE_MAJOR_TYPE_GROUP);
hr = pAudioGroupObj->QueryInterface(IID_IAMTimelineGroup, (void **)&pAudioGroup);
AM_MEDIA_TYPE mtAudio;
ZeroMemory(&mtAudio, sizeof(AM_MEDIA_TYPE));
mtVideo.majortype = MEDIATYPE_Audio;
mtAudio.subtype = MEDIASUBTYPE_PCM;
mtAudio.bFixedSizeSamples = m_mtSrcAudio.bFixedSizeSamples;
//the m_mtSrcAudio is AM_MEDIA_TYPE info. gotten from mpeg file.
mtAudio.lSampleSize = m_mtSrcAudio.lSampleSize;
mtAudio.formattype = FORMAT_WaveFormatEx;
mtAudio.cbFormat = sizeof(WAVEFORMATEX);
WAVEFORMATEX wf;
ZeroMemory(&wf, sizeof(wf));
WAVEFORMATEX *pwf = (WAVEFORMATEX *)m_mtSrcAudio.pbFormat;
wf.nChannels = pwf->nChannels;
wf.nSamplesPerSec = pwf->nSamplesPerSec;
wf.wBitsPerSample = pwf->wBitsPerSample;
wf.nAvgBytesPerSec = pwf->nAvgBytesPerSec;
wf.nBlockAlign = pwf->nBlockAlign;
wf.wFormatTag = WAVE_FORMAT_PCM;
mtAudio.pbFormat = (BYTE *)&wf;
hr = pAudioGroup->SetMediaType(&mtAudio);
hr = pTL->AddGroup(pAudioGroupObj);
hr = pTL->CreateEmptyNode(&pAudioTrackObj, TIMELINE_MAJOR_TYPE_TRACK);
hr = pAudioGroup->QueryInterface(IID_IAMTimelineComp, (void **)&pAudioComp);
hr = pAudioComp->VTrackInsBefore(pAudioTrackObj, 0);
hr = pAudioTrackObj->QueryInterface(IID_IAMTimelineTrack, (void **)&pAudioTrack);
hr = pTL->CreateEmptyNode(&pAudioSourceObj, TIMELINE_MAJOR_TYPE_SOURCE);
hr = pAudioSourceObj->QueryInterface(IID_IAMTimelineSrc, (void **)&pAudioSource);
//Video
hr = pVideoSourceObj->SetStartStop(0, rtStop - rtStart);
hr = pVideoSource->SetMediaName(lpMpegFileName);
hr = pVideoSource->SetStreamNumber(0);
hr = pVideoSource->SetMediaTimes(rtStart, rtStop);
hr = pVideoTrack->SrcAdd(pVideoSourceObj);
//Audio
hr = pAudioSourceObj->SetStartStop(0, rtStop - rtStart);
hr = pAudioSource->SetMediaName(lpMpegFileName);
hr = pAudioSource->SetStreamNumber(1);
hr = pAudioSource->SetMediaTimes(rtStart, rtStop);
hr = pAudioTrack->SrcAdd(pAudioSourceObj);
hr = CoCreateInstance(CLSID_RenderEngine, NULL, CLSCTX_INPROC, IID_IRenderEngine, (void**)&pRender);
hr = pRender->SetTimelineObject(pTL);
hr = pRender->ConnectFrontEnd( );
hr = pRender->GetFilterGraph(&pGraph);
hr = CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL, CLSCTX_INPROC, IID_ICaptureGraphBuilder2, (void **)&pBuilder);
pBuilder->SetFiltergraph(pGraph);
hr = pBuilder->SetOutputFileName(&MEDIASUBTYPE_Avi, lpAviName, &pMux, NULL);
IPin *pPin0 = NULL;
hr = pRender->GetGroupOutputPin(0, &pPin0);
hr = pBuilder->RenderStream(NULL, NULL, pPin0, NULL, pMux);
IPin *pPin1 = NULL;
//below code return: hr=1, means "the group does not have output pin
//why??????
hr = pRender->GetGroupOutputPin(1, &pPin1);
hr = pBuilder->RenderStream(NULL, NULL, pPin1, NULL, pMux);
hr = pControl->Run();
|
|
|
|
|
This is not a coding question, but related to Visual C++.
Here is the situation. I am planning to employ several programmers to help me coding. Is there any way to let them add new classes/dialogs/resources without seeing the implementation of my existing classes/dialogs/resources? Of course I want them to be able to use my classes (the main/base classes), but I don't want them to have the whole code (which I wrote for several years) for security and other reasons.
I would appreciate any suggestions or ideas. Thanks.
|
|
|
|
|
If you have interfaces (pure virtual classes which do define neither member variables nor any implementation or classes which map their interface on your implementation-classes in your code, you can give them only that.
But as you ask here you probably have neither.
Maybe you can get away with giving them a "cleaned up" version of the headers, with any variable declaration and private function removed as an interface.
That way, they could include your code as a closed-source-lib.
Or these guys set up their own set of mock-objects using your interface?
Failure is not an option - it's built right in.
|
|
|
|
|
I don't quite get "cleaned up" header approach. Don't I still need to give them the .cpp files so that they can compile the whole project?
I never created a .lib before (but used many). Is there really a way to give them just the .h files without the .cpp, just like a .lib does? This is really what I am going for: they can see the header, but not the implementation.
P.S.: in the "cleaned up" approach, I simply move the variable declaration and private functions to .cpp file?
Thanks for any help.
|
|
|
|
|
All my musing about possibilities was nothing for the short-term.
But with a (more or less) limited amount of work, you probably could form your code into a library.
The interface of that library needs to be a working c++ header file with all variables and private members.
Maybe that is OK with you.
If you think your contarctors would get too much information from seeing the variable types you defined, you need to go one step further.
Add an Interface-header, which declares a abstract base class.
You (or them) would then have to implement a "mockup-implementation" of this interface. This may be (probably is) a large amount of work.
That way, they could program against the interface, with only you putting the code together.
In the "cleaned" approach, as many private functions as possible are moved out of the class to an anonymous namespace at the top of the cpp-file.
As your contractors never get to see the content of the cpp-file, you are hiding this code from them.
Functions in an anonymous namespace are effectivly static members, and from my experience, an astounding amount of non-trivial static functions could be made static.
Failure is not an option - it's built right in.
|
|
|
|
|
Yup, i think that's the best solution here: to change my code into a library.
Although this only "hides" the code that doesn't deal with dialogs/resources, correct?
Thanks a lot.
|
|
|
|
|