|
Not sure exactly how you're implementing your anchoring, but GetWindowRect get's the coordinates in screen coordinates, but the moving/sizing functions (MoveWindow, SetWindowPos, etc) work in client coordinates.
You can use ClientToScreen and ScreenToClient functions to translate between the two. If you move a parent window, the children will move also, since they're relative to the parent, so you shouldn't need to move the children of the children (but you will need to resize them).
This code will leave the child control at it's current x, y position, but adjust the child width based on the parent width:
::GetClientRect(m_hParentWnd, &rcParent);
::GetClientRect(m_hChildWnd, &rcChild);<br />
<br />
rcChild.right = rcParent.right - ( rcParent.right - rcChild.right );<br />
<br />
::MoveWindow( m_hChildWnd, rcChild.left, rcChild.top, rcChild.right - rcChild.left, rcChild.bottom - rcChild.top, TRUE );<br />
- S
50 cups of coffee and you know it's on!
|
|
|
|
|
Thanks for the reply but the code sample I gave is correct for what I am trying to do. I am specificaly using GetWindowRect() do to the extent of which I have customised the windows. GetClientRect() will no longer give a true reading. Also from my code you should see that I simply calculate the Xoffset and Yoffset then add or subtract this to the childs stored rectangle.
Since I posted the question I have managed to solve it. The first call to my function always comes from the main window, So I can pass in a NULL LPRECT forcing the function to call the GetWindowRect() api. Since this then calculates the new childrens position I can recurse the function passing in the newly calculated childs rectangle. This gives the added advantage of only needing to call the function once from the main window.
|
|
|
|
|
Glad you got it figured out!
- S
50 cups of coffee and you know it's on!
|
|
|
|
|
Hi,
I use dynamically created menus in my application where menu management becomes a complex task.
My problem is that when I get a CMenu pointer (CMenu* pMenu), how can I get the text and ID of the menu pointed by pMenu??
All menu APIs I saw so far deal with child menus, is there a way to get these information using this pointer?? My menu is a popup menu.
Thanks,
Mohammad
And ever has it been that love knows not its own depth until the hour of separation
|
|
|
|
|
The CMenu::GetMenuItemID() and CMenu::GetMenuString() methods should help.
What exactly are you trying to obtain with the CMenu pointer?
Mark
|
|
|
|
|
those method did not help. what I am trying to do is as follows:
I use OnInitMenuPopup(CMenu *pPopupMenu, UINT nIndex, BOOL bSysMenu) msg handler to update the childs of a popup menu item before they are displayed.
I need to know what menu item is exactly being updated, so I want either its ID or its text.
The methods you have posted are declared as follows:
UINT GetMenuItemID(int nPos )const;
int GetMenuString( UINT nIDItem, LPTSTR lpString, int nMaxCount, UINT nFlags ) const;
those deal with the childs of a popup menu item, not the menu item itself.
Any Ideas??
Thanks alot
Mohammad
And ever has it been that love knows not its own depth until the hour of separation
|
|
|
|
|
The 1st level of the popup (the items you see first when it pops up) is pMenu->GetSubMenu(0).
So the top level items can be accessed like this:
pMenu->GetSubMenu(0)->GetMenuString(...)
If the third item (index 2) has a sub menu you could get at it like this:
pMenu->GetSubMenu(0)->GetSubMenu(2)->GetMenuString(...)
|
|
|
|
|
Maybe you have missunderstood me.
What I want is the ID/Name for the parent menu, not the childs!!
Mohammad
And ever has it been that love knows not its own depth until the hour of separation
|
|
|
|
|
Mohammad A Gdeisat wrote: What I want is the ID/Name for the parent menu, not the childs!!
ok sorry.
I don't see any functions or messages to get the parent menu from a child item.
Generally that's all known by whoever builds the menu.
You could start at the top with CWnd::GetMenu() or something and traverse the heirarchy I suppose.
|
|
|
|
|
Hello gurus,
I have a question concerning multi core programming.
I have written a simple independent thread encapsulated in a class that simply display a pixel at a random location and random color.
I can launch the thread on the CPU I want.
I have 4 x64 cores on my computer. So, when I saw the incredible speed I said to my self "ok, if it goes so fast on 1 CPU, it will go 4 time faster on 4 CPUs". So, I decided to create an array of my class that contains the thread and launch the thread on every CPUs with masks { 1, 2, 4, 8 }.
I noticed that it goes slower than it should!
Norally, as I launch 4 threads on 4 different CPUs, it can display simultaneously 4 pixel at a time, so it should give the illusion to go 4 time faster. But it is not the case.
My question is simply... WHY??? Why it goes slower than it should? What I have missed?
Thanks in advance for your answers.
Best regards.
Fred.
There is no spoon.
|
|
|
|
|
bouli wrote: Norally, as I launch 4 threads on 4 different CPUs, it can display simultaneously 4 pixel at a time
You say normally it works but when you do it it's slower? Doesn't make sense.
There's no way it will be 4 times faster. It'll be faster but not a full 4 times. I know
close to nothing about the hardware involved, but I know the processors are sharing the same video
device, the same bus, etc. so it would be impossible to get 4 times the speed.
|
|
|
|
|
That's what surprised me.
Here is the code of the thread:
class CRandomDraw<br />
{<br />
public:<br />
CRandomDraw();<br />
~CRandomDraw();<br />
<br />
void Start();<br />
void Stop();<br />
<br />
void SetCpu(int nCpu);<br />
void SetHwnd(HWND hWnd);<br />
void SetRect(RECT rect);<br />
<br />
private:<br />
BOOL m_bRunning;<br />
DWORD m_dwMask;<br />
HWND m_hWnd;<br />
HDC m_hDC;<br />
HANDLE m_hThread;<br />
HANDLE m_hEvent;<br />
RECT m_rect;<br />
<br />
int m_nCurrentCpu;<br />
<br />
static DWORD WINAPI RandomThread(LPVOID lpParameter);<br />
};<br />
#include "StdAfx.h"<br />
#include "RandomDraw.h"<br />
#include <math.h><br />
<br />
CRandomDraw::CRandomDraw()<br />
{<br />
m_bRunning=FALSE;<br />
m_hWnd=NULL;<br />
m_hDC=NULL;<br />
m_hThread=NULL;<br />
m_hEvent=NULL;<br />
m_nCurrentCpu=0;<br />
m_dwMask=1;<br />
<br />
srand((int) time(NULL));<br />
}<br />
<br />
CRandomDraw::~CRandomDraw()<br />
{<br />
Stop();<br />
<br />
::CloseHandle(m_hEvent);<br />
m_hEvent=NULL;<br />
<br />
::CloseHandle(m_hThread);<br />
m_hThread=NULL;<br />
}<br />
<br />
void CRandomDraw::SetHwnd(HWND hWnd)<br />
{<br />
m_hWnd=hWnd;<br />
m_hDC=GetDC(m_hWnd);<br />
}<br />
<br />
void CRandomDraw::SetRect(RECT rect)<br />
{<br />
m_rect=rect;<br />
}<br />
<br />
void CRandomDraw::SetCpu(int nCpu)<br />
{<br />
m_nCurrentCpu=nCpu;<br />
}<br />
<br />
void CRandomDraw::Start()<br />
{<br />
if (m_bRunning)<br />
return;<br />
<br />
m_bRunning=TRUE;<br />
<br />
m_hThread=::CreateThread(NULL, 0, RandomThread, this, CREATE_SUSPENDED, NULL);<br />
<br />
m_dwMask=(DWORD) pow(2, (double) m_nCurrentCpu);<br />
<br />
::SetThreadAffinityMask(m_hThread, m_dwMask);<br />
<br />
::ResumeThread(m_hThread);<br />
}<br />
<br />
void CRandomDraw::Stop()<br />
{<br />
if (!m_bRunning || !m_hThread)<br />
return;<br />
<br />
m_bRunning=FALSE;<br />
<br />
WaitForSingleObject(m_hEvent, INFINITE);<br />
::CloseHandle(m_hThread);<br />
m_hThread=NULL;<br />
}<br />
<br />
DWORD WINAPI CRandomDraw::RandomThread(LPVOID lpParameter)<br />
{<br />
CRandomDraw* pThis=reinterpret_cast < CRandomDraw* >(lpParameter);<br />
<br />
while (pThis->m_bRunning)<br />
{<br />
::SetPixel(pThis->m_hDC, rand() % pThis->m_rect.right, rand() % pThis->m_rect.bottom, RGB(rand() % 255, rand() % 255, rand() % 255));<br />
<br />
::Sleep(0);<br />
}<br />
<br />
SetEvent(pThis->m_hEvent);<br />
<br />
return 0;<br />
}<br />
The view call the functions like this:
In the header:
<br />
CRandomDraw m_randomDraw[CPU_COUNT];<br />
<br />
void StartAll();<br />
void StopAll();<br />
void SetHwndAll(HWND hWnd);<br />
void SetRectAll(RECT rect);<br />
In the cpp:
void CRandomView::StartAll()<br />
{<br />
for (int i=0; i<CPU_COUNT; i++)<br />
{<br />
m_randomDraw[i].SetCpu(i);<br />
m_randomDraw[i].Start();<br />
}<br />
}<br />
<br />
void CRandomView::StopAll()<br />
{<br />
for (int i=0; i<CPU_COUNT; i++)<br />
m_randomDraw[i].Stop();<br />
}<br />
<br />
void CRandomView::SetHwndAll(HWND hWnd)<br />
{<br />
for (int i=0; i<CPU_COUNT; i++)<br />
m_randomDraw[i].SetHwnd(hWnd);<br />
}<br />
<br />
void CRandomView::SetRectAll(RECT rect)<br />
{<br />
for (int i=0; i<CPU_COUNT; i++)<br />
m_randomDraw[i].SetRect(rect);<br />
}<br />
<br />
BOOL CRandomView::Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext)<br />
{<br />
BOOL bRet=CView::Create(lpszClassName, lpszWindowName, dwStyle, rect, pParentWnd, nID, pContext);<br />
<br />
SetHwndAll(m_hWnd);<br />
StartAll();<br />
<br />
return bRet;<br />
}<br />
<br />
void CRandomView::OnDestroy()<br />
{<br />
StopAll();<br />
CView::OnDestroy();<br />
<br />
}
I think there is nothing special...
Where is it wrong???
There is no spoon. t
|
|
|
|
|
Can you perhaps check the "Ignore HTML tags in this message (good for code snippets)"
checkbox on your reply?
Hard to read your code with < and > missing
|
|
|
|
|
Sure
Random header:
#pragma once
class CRandomDraw
{
public:
CRandomDraw();
~CRandomDraw();
void Start();
void Stop();
void SetCpu(int nCpu);
void SetHwnd(HWND hWnd);
void SetRect(RECT rect);
private:
BOOL m_bRunning;
DWORD m_dwMask;
HWND m_hWnd;
HDC m_hDC;
HANDLE m_hThread;
HANDLE m_hEvent;
RECT m_rect;
int m_nCurrentCpu;
static DWORD WINAPI RandomThread(LPVOID lpParameter);
};
Random implementation (cpp):
#include "StdAfx.h"
#include "RandomDraw.h"
#include <math.h>
CRandomDraw::CRandomDraw()
{
m_bRunning=FALSE;
m_hDC=NULL;
m_hThread=NULL;
m_hEvent=CreateEvent(NULL, TRUE, TRUE, NULL);
m_nCurrentCpu=0;
m_dwMask=1;
srand((int) time(NULL));
}
CRandomDraw::~CRandomDraw()
{
Stop();
::CloseHandle(m_hEvent);
m_hEvent=NULL;
}
void CRandomDraw::SetHwnd(HWND hWnd)
{
m_hWnd=hWnd;
m_hDC=::GetDC(m_hWnd);
}
void CRandomDraw::SetRect(RECT rect)
{
m_rect=rect;
}
void CRandomDraw::SetCpu(int nCpu)
{
m_nCurrentCpu=nCpu;
}
void CRandomDraw::Start()
{
if (m_bRunning)
return;
m_bRunning=TRUE;
m_hThread=::CreateThread(NULL, 0, RandomThread, this, CREATE_SUSPENDED, NULL);
m_dwMask=(DWORD) pow(2, (double) m_nCurrentCpu);
::SetThreadAffinityMask(m_hThread, m_dwMask);
::ResumeThread(m_hThread);
}
void CRandomDraw::Stop()
{
if (!m_bRunning || !m_hThread)
return;
m_bRunning=FALSE;
WaitForSingleObject(m_hEvent, INFINITE);
::CloseHandle(m_hThread);
m_hThread=NULL;
}
DWORD WINAPI CRandomDraw::RandomThread(LPVOID lpParameter)
{
CRandomDraw* pThis=reinterpret_cast<CRandomDraw*>(lpParameter);
while (pThis->m_bRunning)
{
::SetPixel(pThis->m_hDC, rand() % pThis->m_rect.right, rand() % pThis->m_rect.bottom, RGB(rand() % 255, rand() % 255, rand() % 255));
::Sleep(0);
}
SetEvent(pThis->m_hEvent);
return 0;
}
Calls in the SDI view header:
...
private:
CRandomDraw m_randomDraw[CPU_COUNT];
void StartAll();
void StopAll();
void SetHwndAll(HWND hWnd);
void SetRectAll(RECT rect);
afx_msg void OnDestroy();
...
Implementation in the SDI (cpp):
...
BOOL CRandomView::Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext)
{
BOOL bRet=CView::Create(lpszClassName, lpszWindowName, dwStyle, rect, pParentWnd, nID, pContext);
SetHwndAll(m_hWnd);
StartAll();
return bRet;
}
...
void CRandomView::OnSize(UINT nType, int cx, int cy)
{
CView::OnSize(nType, cx, cy);
// TODO: Add your message handler code here
RECT rect;
GetWindowRect(&rect);
SetRectAll(rect);
}
void CRandomView::StartAll()
{
for (int i=0; i<CPU_COUNT; i++)
{
m_randomDraw[i].SetCpu(i);
m_randomDraw[i].Start();
}
}
void CRandomView::StopAll()
{
for (int i=0; i<CPU_COUNT; i++)
m_randomDraw[i].Stop();
}
void CRandomView::SetHwndAll(HWND hWnd)
{
for (int i=0; i<CPU_COUNT; i++)
m_randomDraw[i].SetHwnd(hWnd);
}
void CRandomView::SetRectAll(RECT rect)
{
for (int i=0; i<CPU_COUNT; i++)
m_randomDraw[i].SetRect(rect);
}
void CRandomView::OnDestroy()
{
StopAll();
CView::OnDestroy();
// TODO: Add your message handler code here
}
...
Maybe I have missed something.
As I said, normally, the pixels should be displayed CPU_COUNT faster because there are CPU_COUNT threads running on separate CPU, while each CPU runs 1 thread. So, 4 pixels at a time should be displayed. But it is much slower than running 1 thread. This is a paradox. And what I don't understand.
Thanks to help me to solve my problem
Best regards.
Fred.
There is no spoon.
|
|
|
|
|
What happens if you remove the ::Sleep(0); call from your thread proc (don't let the threads give
up any of their time slice)?
You're still not going to get 4 times as fast since you have device contention at the display
device.
I wouldn't think it would be slower though
|
|
|
|
|
Hi,
Sleep(0) is supposed to free the thread's quantum allocated by the system.
I removed it but it is still slower as if it would run on 1 CPU which is paradoxal.
There is no spoon.
|
|
|
|
|
bouli wrote: Sleep(0) is supposed to free the thread's quantum allocated by the system.
Right - I was wondering what would happen if you let the threads use their entire time-slice;
I don't know what goes on with processor cache and bus and RAM contention but just at the
SetPixel() call alone, only one thread will be able to write a pixel at a time unless your video
device can parallel process the calls.
I don't think it's paradoxal. I think the fastest performance you could get would be to have one
thread that does the IO (output a pixel) and 3 threads calculating the random coordinates and
feeding them to the pixel-outputter-thread. Just a guess, I could be way off
When you run it what does performance monitor show for CPU usage?
|
|
|
|
|
Example fromm Google search ("multicore percent faster"):
From Performance Analysis and Multicore Processors[^]...
"One of the side effects of multicore technology is that CPU-bound applications can
potentially run twice as fast on dual-core processors, whereas memory-bound applications may only
run 50 percent faster. I/O-bound applications may not run any faster"
|
|
|
|
|
PROBLEM DESCRIPTION
I have a CFormView based SDI application. There is a button and a Editbox (m_Progress , a control category CEdit variable, indicating program progress) on the form. A lengthy task will be started by clicking the button. Usually the task will take several hours. While the process is running, users may use other applications, such as WORD, EXCEL,etc,. When users get back to the process to see its progress. The window cannot be maxmized. To solve this problem, I read some articles. A lot of articles suggest that thread should be used.
So, i decide to use a worker thread to solve this problem. To this end, I move the code in the original button-cick handler to a function (SubFunc())of a class (MyClass). In the new button-click handler I first creat an instance of MyClass. Then, pass the instance to AfxBeginThread() to create a worker thread. The above steps are implented as follows.
UINT MyThreadProc(LPVOID pParam)
{
MyClass* pObject = (MyClass*)pParam;
if (pObject == NULL)
{
return -1;
}
else
int test = pObject->SubFunc();
return 0;
}
}
void CHhhhView::OnButton1()
{
MyClass *objMyClass = new MyClass;
AfxBeginThread(MyThreadProc, objMyClass);
}
In SubFunc(), I use following statements to send the string "9999" to m_Progress. Specially, ((CMDIFrameWnd*)AfxGetMainWnd()->GetActiveWindow())->GetActiveDocument() is used.
CDocument* pp = ((CMDIFrameWnd*)AfxGetMainWnd()->GetActiveWindow())->GetActiveDocument();
POSITION vv = pp->GetFirstViewPosition();
POSITION pos = pp->GetFirstViewPosition();
if (pos != NULL)
{
CHhhhView* pView = (CHhhhView*)pp->GetNextView(pos);
if(pView!=NULL)
{
pView->m_Progress.SetWindowText("9999");
pView->UpdateWindow();
}
}
However, ((CMDIFrameWnd*)AfxGetMainWnd()->GetActiveWindow())->GetActiveDocument() works
only when objMyClass is NOT called
in a worker thread.
That is, objMyClass is called in the following way,
void CHhhhView::OnButton1()
{
MyClass mc;
mc.SubAdd();
int itmp = mc.m_itmp;
}
I noticed an artical
http://www.codecomments.com/archive372-2006-4-890607.html[^], which highly associated with my problem. However, I still could not figure out the solution, as I am a newbie to MFC.
* Am I in the right direction to solve the problem correctly caused by lengthy task by using a worker thread?
* What is a good way to wire the CEdit control and the varible updated in the SubFunc() running in a worker thread.
Please help me. This problem has stumped me for serveral days .
-- modified at 17:25 Saturday 4th November, 2006
|
|
|
|
|
GetActiveWindow() is thread-specific. You have no active windows in your worker thread.
Why not add a CHhhhView* member to your MyClass class (pass it in in the constructor):
class MyClass
{
CHhhhView *pView;
public:
MyClass(CHhhhView *view) {pView = view;}
};
void CHhhhView::OnButton1()
{
MyClass *objMyClass = new MyClass(this);
AfxBeginThread(MyThreadProc, objMyClass);
}
Now you can use pView in MyClass instead of ((CMDIFrameWnd*)AfxGetMainWnd()->GetActiveWindow()).
|
|
|
|
|
:-DThank you Mark very much for your reply. It works for me.
|
|
|
|
|
One more question about this topic.
Where and how should the pointer 'objMyClass' be deleted to prevent memory leak. I think this should be done at the end of SubFunc(). However, I am not very sure.
|
|
|
|
|
cy163@hotmail.com wrote: Where and how should the pointer 'objMyClass' be deleted to prevent memory leak.
Any time after the pObject->SubFunc() call (obviously)
There's alot of people who object to deleting objects in a different thread than the thread the
object was created in. If you are using new/delete this is perfectly legal to do, so IMO it
comes down to preference.
If it's clear in the code that you create an object (using new) and send it off to a worker
thread to be processed, and that the worker thread will delete it when it's finished, then delete
it in the thread proc when you're finished with it.
If you want to delete it in the same thread it was created in (the UI thread in your example)
then you could use PostThreadMessage() from the worker thread to send the pointer back to the UI
thread for deletion when it's finished with it. The worker thread would need to know which thread
it came from to know where to post the message to.
cy163@hotmail.com wrote: I think this should be done at the end of SubFunc(). However, I am not very sure.
I personally wouldn't do it IN the SubFunc() function. That would be, IMO, too buried to be clear
in the code what's going on. Right after the pObject->SubFunc() call a "delete pObject;" would
be fine.
I would just make sure to document it well in the code with comments so when you possibly enhance
the code later you know exactly where objects are bing deleted, something like this:
void CHhhhView::OnButton1()
{
MyClass *objMyClass = new MyClass;
AfxBeginThread(MyThreadProc, objMyClass);
}
Whatever it takes to make sure you always know that you shouldn't use objMyClass later because
at any time the worker thread will delete it
|
|
|
|
|
Thank you Mark for your clear explanation.
One more further question, also about mem leak. i have some dynamically allocated variables (using malloc(), new) in SunFunc(). I wonder if those allocated mem can be deallocated automatically after the thread finished successfully. Or, i have to take care of the memory releasing things myself.
Moreover, could you please talk about how to terminate the thread before SubFunc() reaches its end in my example. I refer to some articles. They suggested to use CEvent and WaitForSingleObject(), as well as AfxEndThread().
I do not how to combine them to terminates a thread from another thread (main thread, in my case).
Thank you for your valuable time
-- modified at 6:10 Monday 6th November, 2006
|
|
|
|
|
Hi,
I want to create a child window with menu like in a SDI application from a dialog based application. How to create it?
Cyber Friend
|
|
|
|
|