Codejock Forums Homepage
Forum Home Forum Home > Codejock Products > Visual C++ MFC > Docking Pane
  New Posts New Posts RSS Feed - Docking panes - no WM_WINDOWPOSCHANGING
  FAQ FAQ  Forum Search   Events   Register Register  Login Login

Docking panes - no WM_WINDOWPOSCHANGING

 Post Reply Post Reply
Author
Message
Matchay View Drop Down
Newbie
Newbie


Joined: 25 May 2005
Location: Germany
Status: Offline
Points: 9
Post Options Post Options   Thanks (0) Thanks(0)   Quote Matchay Quote  Post ReplyReply Direct Link To This Post Topic: Docking panes - no WM_WINDOWPOSCHANGING
    Posted: 15 June 2005 at 6:28am

Hello!

I am struggling with integrating MFC/XTreme Toolkit Pro into an old application, where the main window was written in API (and there's no chance to rewrite it in MFC).

I managed to create an object of CXTPFrameWnd class and subclass the application window. It works fine then, I can create the Pane Manager and panes, attach windows to panes and so on, but I can't fight over a few problems with refreshing positions of panes and splitter gripper.

Look here, this is the initial state:

then I click the "pin" to hide the pane, but it seems just to disappear:

so I slightly move the Menu Bar around and only then the whole area gets updated:

Generally in most of sizing/positioning actions the pane's position gets updated only when I explicitely move for example the Menu Bar. Sometimes you can see that the splitter gripper doesn't stick to the pane, sometimes it suddenly gets very wide, being the size of the whole window.

What I noticed when debugging with Spy++ is that e.g. on moving the gripper to resize the pane there's no WM_WINDOWPOSCHANGING message being sent around. I noticed that this message should be sent by the gripper , but it seems it's neither sent or receieved by the pane.

I guess it must be about message routing but I have no idea what should I fix.Any ideas would be really appreciated.

Regards!

Maciej

Back to Top
Matchay View Drop Down
Newbie
Newbie


Joined: 25 May 2005
Location: Germany
Status: Offline
Points: 9
Post Options Post Options   Thanks (0) Thanks(0)   Quote Matchay Quote  Post ReplyReply Direct Link To This Post Posted: 15 June 2005 at 7:06am

One more thing: when redocking the pane, for example from the left side to the top edge of the frame it disappears and the OnDockingPaneNotify message comes only when I move the toolbar. Then the pane reappears at the right position.

Maciej

Back to Top
Oleg View Drop Down
Admin Group
Admin Group


Joined: 21 May 2003
Location: United States
Status: Offline
Points: 11234
Post Options Post Options   Thanks (0) Thanks(0)   Quote Oleg Quote  Post ReplyReply Direct Link To This Post Posted: 17 June 2005 at 7:23am
You must make all appliaction MFC based. DockingPanes need

WM_IDLEUPDATECMDUI message to update its state.

Oleg, Support Team
CODEJOCK SOFTWARE SOLUTIONS
Back to Top
Stephen12 View Drop Down
Newbie
Newbie


Joined: 20 July 2005
Status: Offline
Points: 5
Post Options Post Options   Thanks (0) Thanks(0)   Quote Stephen12 Quote  Post ReplyReply Direct Link To This Post Posted: 27 July 2005 at 11:24am

As Oleg said you need to have WM_IDLEUPDATECMDUI send to your panes. Your main message loop doesn't have it, so you need to "fake" MFC framework behavior. 

One solution is to create timer in your CXTPFrameWnd that will send this message to all the panes.

Good place for creating timer is in your CMyFrameWnd::OnCreate of the FrameWnd.

 

SetTimer(EVENT_IDLEUPDATE, 150, NULL);

 

Add handler for WM_TIMER

 

CMyFrameWnd::OnTimer(UINT nIDEvent)

{

if(nIDEvent == EVENT_IDLEUPDATE && m_hWnd)

{

if (m_nShowDelay == SW_HIDE)

ShowWindow(m_nShowDelay);

// send WM_IDLEUPDATECMDUI to yourself and descendants - one of them is pane manager

if (IsWindowVisible() || m_nShowDelay >= 0)

{

AfxCallWndProc(this, m_hWnd,WM_IDLEUPDATECMDUI, (WPARAM)TRUE, 0); //send it to yourself

SendMessageToDescendants( WM_IDLEUPDATECMDUI,(WPARAM)TRUE, 0, TRUE, TRUE); //send it to your children, one of them is PaneManager

}

// send WM_IDLEUPDATECMDUI to the floating miniframewnd

// and its descendants

// walk through all top-level windows, these windows are owned by frame but they aren't its children - they are children of desktop instead. You need to update them too or your floating windows will be funny like your docked one is now

HWND hWnd = ::GetWindow(::GetDesktopWindow(), GW_CHILD);

while (hWnd != NULL)

{

CWnd* pWnd = CWnd::FromHandlePermanent(hWnd);

if (pWnd != NULL && m_hWnd != hWnd && pWnd->GetOwner() == this

&& pWnd->IsKindOf(RUNTIME_CLASS(CXTPDockingPaneMiniWnd)))

{

AfxCallWndProc(pWnd, pWnd->m_hWnd,

WM_IDLEUPDATECMDUI, (WPARAM)TRUE, 0);

pWnd->SendMessageToDescendants( WM_IDLEUPDATECMDUI,(WPARAM)TRUE, 0, TRUE, TRUE);

}

hWnd = ::GetWindow(hWnd, GW_HWNDNEXT);

}

}

 

if (m_nShowDelay > SW_HIDE)

ShowWindow(m_nShowDelay);

m_nShowDelay = -1;

}

else

{

//handle other events

CXTPFrameWnd::OnTimer(nIDEvent);

}

I hope this will give you idea! Regards,

- Slobodan

 

Back to Top
jaredf View Drop Down
Newbie
Newbie


Joined: 13 October 2005
Status: Offline
Points: 4
Post Options Post Options   Thanks (0) Thanks(0)   Quote jaredf Quote  Post ReplyReply Direct Link To This Post Posted: 13 October 2005 at 10:21am
Great post, fixed my problem also!
Back to Top
Stephen12 View Drop Down
Newbie
Newbie


Joined: 20 July 2005
Status: Offline
Points: 5
Post Options Post Options   Thanks (0) Thanks(0)   Quote Stephen12 Quote  Post ReplyReply Direct Link To This Post Posted: 13 October 2005 at 11:37am

I am not big fan of timer solution, but it was easier to paste some real code. Even better solution is to change your main windows message loop in trying to simulate MFC behaviour by kicking idle if there are no messages in your queue for certain time (or more precise there are no messages that are important updating your UI - search MFC code for AfxInternalIsIdleMessage()). You would then call into your DLL based on CodeJock. There you just transfer call to your instance of CWinApp, in fact to its OnIdle() method. If you see how MFC loop is implemeted you will notice counters that provide facility for task separation , but you may not need to be so perfect to implement counter logic in your main windows message loop. It should be enough to pass parameter -1.

So, something like

CMyCodeJockBasedDllApp.OnIdle(-1) 

in your MFC part shall do the magic.

 

Main part will be to change your windows message loop so that instead of 

while((bRet =GetMessage(...))!=0)
{

  ...  

  TranslateMessage(...);

  DispatchMessage(...);

}

you  PeekMessage(...) first, see if it is the one that is important for UI (see AfxInternalIsIdleMessage()) , if yes set some flag that you want to triger OnIdle and process the message, if no just process the message (GetMessage, Translate, Dispacth). If there are no messages in your queue see your flag and if it is set make call to your CodeJock based DLL and reset it. If not just wait for your next message.

The advantage of this solution is that it triggers idleupdatecmdui only when needed and there is nothing else to do, not when the timer ticks.

 

 

Back to Top
jaredf View Drop Down
Newbie
Newbie


Joined: 13 October 2005
Status: Offline
Points: 4
Post Options Post Options   Thanks (0) Thanks(0)   Quote jaredf Quote  Post ReplyReply Direct Link To This Post Posted: 18 October 2005 at 11:42am
Thanks for the feedback.  As it turns out in my scenario, the WinApp was already handling the OnIdle and pumping WM_IDLEUPDATECMDUI messages to descendants but not parents.  Upgrading this forwarding to send to both principles and descendants eliminated the need to use the timer.
Back to Top
 Post Reply Post Reply
  Share Topic   

Forum Jump Forum Permissions View Drop Down

Forum Software by Web Wiz Forums® version 12.04
Copyright ©2001-2021 Web Wiz Ltd.

This page was generated in 0.188 seconds.