|
Thanks for the answer, you check perfectelly my problem.
I have read the article you link and I try to implement the first solutiona you've suggested.
I made my CMyThread class derived from CWinThread class and create the thread in my app when I need to call the ActiveX functions.
I have some problem:
1. In code when I need to create the Thread attach this code:
CMyThread * thread = AfxBeginThread(RUNTIME_CLASS(C4Thread));
but at compile-time it said "It's impossible to convert from 'CWinThread *' to 'CMyThread *'.
WHY this?
2. In which method of my CMyThread class I must put the code to peform (the call to the ActiveX functions) or I need to implement a new function? In thi case how?
Thanks a lot.
|
|
|
|
|
CDRAIN wrote: I try to implement the first solutiona you've suggested
Well, my first suggested solution wasn't not about UI-threads. It was about modifying the ActiveX control since it would be the best designed and easiest solution.
Your problem is due to the ActiveX control being poorly designed, or you're using it in a way it wasn't intended.
Do you have access to the source code for the ActiveX and can you make modifications to it?
I don't want to encourage you to take the path to a less suitable solution (the UI-thread alternative) unless forced to. :->
"It's supposed to be hard, otherwise anybody could do it!" - selfquote "High speed never compensates for wrong direction!" - unknown
|
|
|
|
|
Sorry, I want to say that I try your second solution...
I don't have access to the source code for the ActiveX, so I try the UI-Thread.
I try to explain my problem: on my thread I must fill a grid control (the ActiveX) and while this i need to refresh a progress bar.
This is the code I use:
Create the thread in which I'll fill the grid
C4ThrGrid * thread = (C4ThrGrid *)AfxBeginThread(RUNTIME_CLASS(C4ThrGrid));
Call the thread's function that fill the grid
thread->openGrid(&m_wndGrid,str,m_inUseSource);
Close the thread is it right
thread->PostThreadMessage(WM_QUIT, 0, 0);
Is it the right way to obtain what I need?
Why at runtime when I create the thread appear a message box that said "Insufficent Memory"
Help!!!!
|
|
|
|
|
CDRAIN wrote: Sorry, I want to say that I try your second solution...
Quite allright, I was only making sure that what I wrote made sense.
CDRAIN wrote: I don't have access to the source code for the ActiveX, so I try the UI-Thread.
Ok. Too bad, though.
This is, like I wrote earlier, not easily circumvented.
CDRAIN wrote: Can you helo whit my problem?
Yes, I can, but I have a limited amount of time so you shouldn't rely on me solely.
If you're not familiar with the things I mentioned in my earlier post, like UI-threads, STA, marshalling and so on; you should expect quite a learning curve before you're done with this.
But consider that a great opportunity to learn!
Regarding your previous post:
You don't need a CMyThread* member variable. You will only need a CWinThread* variable. The CMyThread class is only needed for the implementation of what the thread should do, respond to messages and what messages to react upon.
Changing the type to CWinThread* will remove your compiler error.
You don't "call" functions in a thread. You comunicate with a UI-thread by posting messages to and from the thread.
Read the article I referred to again, carefully.
The article describes what you have to do, including where to call ::CoInitialize() and ::CoUninitialize() in order to create and tear down the STA.
The first step is to successfully spawn the UI-thread and be able to stop it later.
Before you're finished you also have to:
- Marshal the ActiveX interface back to the main thread with calls to
::CoMarshalInterThreadInterfaceInStream(...) and ::CoGetInterfaceAndReleaseStream(...) - Post a message to the UI-thread when the lengthy operation should be performed with <ode>PostThreadMessage(...)
- Set a timer to update your progress bar and implement the timer message handler with
CWnd::SetTimer(...) and override CWnd::OnTimer(...) - Post a message from the UI-thread when the lengthy operation has completed with
PostMessage(...) - Release the interfaces when you're done in both the main thread and the UI-thread
- Terminate the UI-thread by posting a WM_QUIT message and wait for it to die with a call to
::WaitForSingleObject(...) waiting on the thread handle
I suggest you start a new thread for each question you have and you should probably link to this forum thread to explain the background.
"It's supposed to be hard, otherwise anybody could do it!" - selfquote "High speed never compensates for wrong direction!" - unknown
|
|
|
|
|
Thanks a lot for the help... ok I'm able to create a UI-Thread from my MainWnd as I need to get the ActiveX functionality.
My Activex must fill the grid contained on the MainWnd, while the progressBar is incremented.
So I set the timer, that increment the progressbar on the OnTimer event, and create the ui-thread using this code I use:
<br />
thread = new CMyThread();<br />
thread->GripPointer= GridPointer;<br />
thread->par2 = par2;<br />
thread->par3 = par3;<br />
thread->CreateThread();<br />
On my ui-thread code i fill the grid on the Run() method and at the end of the operation I PostMessage(..) to the MainWnd and here I close the ui-thread sending a
PostMessage(WM_INFORM_CLOSE, 0, 0); .
At Run-Time it gives me an error "Not valid pointer' when i call the function to fill the grid on the ui-thread.
WHY?
- Where I need to use the ::CoMarshalInterThreadInterfaceInStream(...) and ::CoGetInterfaceAndReleaseStream(...) method you said, and witch is they're scope? (Sorry I'm newer in this use )
- Have you an example code?
Another question:
But can I manage a graphic component of the MainWnd (the grid) from the ui-thread?? Is this my problem?
Thanks a lot
|
|
|
|
|
I'm afraid that this solution may be a little bit too complex.
You ask about accessing graphic components in the main window from the UI-thread and whether this is a problem or not. The answer is "it depends on how you do it". You cannot access the components directly since your call is made from another thread and the object map is per thread basis. What you do is post WM_COMMAND messages to the different UI objects in the main window.
I suggest that you revert to my alternative suggestion in my first post: spawn a thread that displays a dialog box with a progress bar prior to starting the lengthy operation from the main thread.
This will save you the trouble of marshalling, sending WM_COMMAND messages to graphic components of the main window etc.
Since it's not possible to implement the "best solution", i.e. refactor the ActiveX component and make it asynchronous, you don't have to make things more complex than necessary. It would be nice to have the ActiveX in another apartment as I suggested, but given your latest reply I realize that it's overly complicated.
The user won't see any difference and in either case he/she won't be able to cancel the lengthy operation, so there's no point in having a "Cancel"-button in the dialog.
"It's supposed to be hard, otherwise anybody could do it!" - selfquote "High speed never compensates for wrong direction!" - unknown
|
|
|
|
|
Hi everybody,
If i size the frame, the view also resizes and should adapt the controls.
I wrote already some classes which increases/decreases f.ex. the grid,
repositionate the control for that a button is always at the bottom, ...
I use for this work the "MoveWindow" Funktion.
All will be done in the OnSize-Handler
At the end i set all controls to Invalidate.
In a specific Child-Window i have a very complex structure.
Frame -> View -> TabControl -> Views -> There'in another TabControl -> View
if i size the Frame, all controls inside must be resized.
I SUPPOSE an OnSize-Event is handled via PostMessage, because during the sizing, a delay is
produced in the sub-views.
need i to change the entire Sizing-Message-System for that all Controls (Views,TabControls) are sizing
at the same time?
Big thanks
|
|
|
|
|
I have similar window heirarchy in my apps and all move/resize at the same time.
You shouldn't have to call Invalidate if you use the repaint flag in MoveWindow.
All WM_SIZE messages need to be handled through your window heirarchy where needed.
There should be no delay, unless you coded it that way .
"Posting a VB.NET question in the C++ forum will end in tears." Chris Maunder
|
|
|
|
|
Thanks for your reply
Is it possible that the resizing of all sub-controls ( 2 TabControls, Buttons, Grids,...) takes
too long and the sizing of the frame is faster then the execution of all resizing-operations?
Because all sizes correctly, but the frame has always a lead on the controls.
If i stop to resize, then the controls are catching up the frame and the controls have the correct size.
I have an OutlookBar and a TabWnd in the MainView. In the TabWnd, in each Tab a View, there in a TabWnd and in each Tab again a View.
All contents from up the first TabWnd are sizing at the same time as the TabWnd it selfs.
But only the OutlookBar and Main-TabWnd are sizing with a delay
|
|
|
|
|
baerten wrote: But only the OutlookBar and Main-TabWnd are sizing with a delay
Hmm how are they being resized by the main view?
What do you see when you drag the border of the main frame? If you just see a rectangle then
you may need to change your display settings to show window contents while resizing.
Mark
"Posting a VB.NET question in the C++ forum will end in tears." Chris Maunder
|
|
|
|
|
I have a generic View-Class, called UniView. All my views are derived from UniView.
In UniView i color for example the background in light-blue;
If i resize the frame, the frame-border is displayed totally correctly.
The view is also displayed correctly ( the new created space is also light-blue )
I resize the TabWnd and OutlookBar via MoveWindow.
if i size the frame for example for 50pixel larger in a normal sizing speed.
The TabWnd (which takes 3/4 of all the space of the view, the OutlookBar 1/4) sizes in
spaces. F.ex. alyways after 5pixels. Thats the delay
I removed the some controls/views and all slides correctly.
Propably i have an performance leak in a specific view or all operations together are taking
too long time.
Big thanks nevertheless
|
|
|
|
|
I do all the MoveWindow() calls in response to WM_SIZE in the parent windows.
Your outer frame window's OnSize() handler should call MoveWindow() for the Tab window.
The tab window's OnSize() handler should resize the control and reposition the active view.
I personally use ::BeginDeferWindowPos()/::DeferWindowPos()/::EndDeferWindowPos() to do the two
movewindows simultaneously. It performs well.
The tab view window's OnSize() handler should call MoveWindow() for all the controls that need to
be repositioned.
And so on...
I would take a look at how you are resizing your tab window. I bet the problem is there
In my code, the tab controls are attached to the frame window in an OnCreateClient() override
so MFC handles repositioning the tab control to fit the window.
In the tab control's OnSize() handler (I had to derive from the CTabCtrl class to do this) I
do the two window resizes I mentioned above. The code is like this:
void CMainFrameTabCtrl::OnSize(UINT nType, int cx, int cy)
{
CTabCtrl::OnSize(nType, cx, cy);
if (pMainFrame && ::IsWindow(*pMainFrame))
pMainFrame->TabWindowResize();
}
...
...
void CMainFrame::TabWindowResize()
{
if (pTabs && (pTabs->m_hWnd != 0))
{
CRect CliRect;
pTabs->GetWindowRect(&CliRect);
::MapWindowPoints(0, *pTabs, (LPPOINT)&CliRect, 2);
TabClientRect = CliRect;
pTabs->AdjustRect(false, &TabClientRect);
::MapWindowPoints(*pTabs, *this, (LPPOINT)&TabClientRect, 2);
int i = pTabs->GetCurSel();
if (i >= 0 && TabClients[i] && TabClients[i]->m_hWnd)
{
HDWP hDwp;
if ((hDwp = ::BeginDeferWindowPos(2)) != 0)
{
hDwp = ::DeferWindowPos(hDwp,*pTabs,0,0,0,
CliRect.Width(),CliRect.Height(),
SWP_NOMOVE | SWP_NOZORDER);
hDwp = ::DeferWindowPos(hDwp,*TabClients[i], HWND_TOP,
TabClientRect.left,TabClientRect.top,
TabClientRect.Width(),TabClientRect.Height(), 0);
::EndDeferWindowPos(hDwp);
}
}
}
}
I hope that helps a bit!
Mark
"Posting a VB.NET question in the C++ forum will end in tears." Chris Maunder
|
|
|
|
|
Hi all,
I'm trying the following:
token = strtok( buffer, seps );
while( token != NULL )
{
updbuff[x] = token;
_splitpath(updbuff[x],drive, dir, fname, ext);
sprintf((char*)updpathbuff, "%s.%s",fname, ext);
h_updPathbuff[x] = updpathbuff;
token = strtok( NULL, seps );
x++;
}
But with every loop occurrence, I overwrite the pointer h_updPathbuff .
I know what the problem is, but I don't know how to fix it
Can someone please help.
Thanks in advance.
Regards,
The only programmers that are better than C programmers are those who code in 1's and 0's.....
Programm3r
My Blog: ^_^
|
|
|
|
|
Instead of copying the pointer, you should copy the contents of the pointer. updpathbuff will always point at the same memory location, so if you store this pointer in an array and then you write something else in it, the contents of the pointer in the array will also change (because both pointers point at the same memory location). So, what you should do is use strcpy to copy the contents in a new pointer. But you should be carefull doing this: the pointer where you copy the data should be valid and the allocated memory should be big enough to accept the data.
I highly suggest that you copy the content in a std::string instead, so you'll get rid of all the problems of memory management.
|
|
|
|
|
|
Hi
All
I create owner drawn menu in VC++6.0 and now i want to create my own font and set it to menu and its items so that menu will display in desired font.So please give some hint that where i write code for creating font.
Regards
Atool
|
|
|
|
|
|
|
See WM_CTLCOLORBTN for button and WM_CTLCOLOREDIT for edit constols
|
|
|
|
|
|
MSDN has examples but see here[^]
|
|
|
|
|
|
Also note that it won't work for buttons unless they are owner-draw buttons.
WM_CTLCOLOR works on edit controls fine.
Mark
"Posting a VB.NET question in the C++ forum will end in tears." Chris Maunder
|
|
|
|
|
When I try to compile my old code in Visual C++ 2005, I get the error message
error C2990: 'Cg2HashTable' : non-class template has already been declared as a class template
with the code
<br />
<br />
template <class lType><br />
class Cg2FixedList;<br />
<br />
template <class keyType, class dataType><br />
class Cg2HashTable;<br />
<br />
template <class KEY, class DATA><br />
class Cg2SortedList;<br />
<br />
<br />
class Cg2DataHandle {<br />
<br />
private:<br />
friend class Cg2FixedList;<br />
friend class Cg2HashTable;<br />
friend class Cg2SortedList;<br />
...............<br />
<br />
How can I fix this? Thanks!
Nacho
|
|
|
|
|
Hello,
I am trying to convert my project to use Visual C++ 2005. However, when I compile my project, I get a lot of warning message like this,
c:\dxsdk\include\d3d9types.h(1385) : warning C4819: The file contains a character that cannot be represented in the current code page (950). Save the file in Unicode format to prevent data loss
How can I fix this? Thanks!
Nacho
|
|
|
|
|