Solved

MFC Programming question

Posted on 1997-09-23
17
458 Views
Last Modified: 2013-11-20
Is it possible to disable the move of the window without
hiding the titlebar (like patching GetMinMaxInfo for
disabling the resize of the window) ?
Thanx.
0
Comment
Question by:onyxmedia
  • 7
  • 6
  • 3
  • +1
17 Comments
 
LVL 3

Expert Comment

by:jaba
Comment Utility
Yeah. you should dispatch WM_WINDOWPOSCHANGING message. Lparam of this message is pointer to WINDOWPOS structure. You have to set flags member to SWP_NOMOVE.
Or you can change x, y, cx , cy ... members to initial values :-)
For more information look for you SDK documentation. Using flags member method usable for WIN32 but i am not sure about WIN16. But setting x,y,  cx, cy members to i nitial values is usable in WIN16 ( i am sure).
This message also usable for resizing window on  fixed dimentions.
0
 
LVL 10

Expert Comment

by:RONSLOW
Comment Utility
Write a handle for WM_NCHITTEST, call the base class implementation, and change any return of HTCAPTION into HTBORDER (or maybe HTCLIENT).  If the hit test is HTCAPTION, the you can move etc with the mouse - changing the return value to something else changes the behaviour of the mouse.

Please reject previous and so I can submit this one if you prefer it.

0
 
LVL 3

Expert Comment

by:jaba
Comment Utility
Well, well. I am sure, you never seen Windows. Caption usable NOT ONLY for moving window (it usable for maximizingwindow TOO). Its posssible to move window WITHOUT dragging it by caption. (see system menu). Go, Ronslow, lets try to disable THIS method of window moving.

0
 
LVL 10

Expert Comment

by:RONSLOW
Comment Utility
Hey - don't get nasty !!  I HAVE seen windows, thank you very much (you wanna compare expert ratings here? or years of programming experience?).

I simply provided an alternative method of preventing window movement by dragging.

And I DO know there are other ways to move a window than by the title bar, and there are other uses for the titlbe bar.

Your answer seemed a bit confusing, talking about dispatching a WM_WINDOWPOSCHANGING.  Did you really mean providing a handler or reponding to the message?  And don't forget to NOT call the base class.

BTW: You can easily disable the system menu options for moving (and other system menu options).

0
 
LVL 10

Expert Comment

by:RONSLOW
Comment Utility
Here's how...

void CMainFrame::OnInitMenuPopup(CMenu* pMenu, UINT nIndex, BOOL bSysMenu)
{
      if (bSysMenu && !m_bSysMenuInitialized) {
            pMenu->RemoveMenu (SC_MOVE,    MF_BYCOMMAND);
            pMenu->RemoveMenu (SC_SIZE, MF_BYCOMMAND);
            pMenu->RemoveMenu (SC_RESTORE, MF_BYCOMMAND);
            pMenu->RemoveMenu (SC_MINIMIZE,MF_BYCOMMAND);
            pMenu->RemoveMenu (SC_MAXIMIZE,MF_BYCOMMAND);
            pMenu->RemoveMenu (SC_TASKLIST,MF_BYCOMMAND);
            for (UINT i=0; i<pMenu->GetMenuItemCount(); i++) {
                  if (pMenu->GetMenuItemID(i) == 0) { // (if separator)
                        pMenu->RemoveMenu (i, MF_BYPOSITION);
                        continue;
                  }
            }
            m_bSysMenuInitialized = TRUE;
      }
      CFrameWnd::OnInitMenuPopup(pMenu, nIndex, bSysMenu);
}

void CMainFrame::OnNcLButtonDblClk(UINT nHitTest, CPoint point)
{
      if (nHitTest==HTCAPTION) return;
      CFrameWnd::OnNcLButtonDblClk(nHitTest, point);
}

void CMainFrame::OnSysCommand(UINT nID, LPARAM lParam)
{
      switch (nID & 0x0fff0) {
      case SC_MINIMIZE:
      case SC_RESTORE:
      case SC_NEXTWINDOW:
      case SC_PREVWINDOW:
      case SC_TASKLIST:
      case SC_SIZE:
      case SC_MOVE:
            return;             // (don't do anything)
      }
      CFrameWnd::OnSysCommand(nID, lParam);
}

BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
{
      if (! CFrameWnd::PreCreateWindow(cs)) return FALSE;
      cs.style &= ~WS_MINIMIZEBOX;
      cs.style &= ~WS_MAXIMIZEBOX;
      return TRUE;
}

0
 
LVL 3

Expert Comment

by:jaba
Comment Utility
This is MY solution.

void CMainFrame::OnWindowPosChanging(WINDOWPOS FAR* lpwndpos)
{
      CMDIFrameWnd::OnWindowPosChanging(lpwndpos);
    lpwndpos->flags |= SWP_NOMOVE;
   
}

0
 
LVL 10

Expert Comment

by:RONSLOW
Comment Utility
Well there you go.

How will that affect (if at all) initial creation of the main window?  It seems a little harsh rejecting ALL window movements.

Of course, there is also the fact that the user can still try to move the window, and system menu options are still there for doing so, but nothing will happen.  It is better to get rid of the commands (or at least disable them) so it doesn't appear to the user that his system just isn't working any more.  I don't think your solution on its own is the best way to go UI-wise.

Maybe a combination of the two solutions here would be best.

0
 
LVL 3

Expert Comment

by:jaba
Comment Utility
Well. I made small test programm (by MSVC appwizard) and  wrote its  code. All working nice. While initial window creation window never recive WM_MOVE message, only WM_SIZE. What why its  dont  affect  initial creation.
Really, this work correct, but look ugly (because while dragging   window user can see dragging  rectangle but window dont move after  you release mouse button). To avoid it need add few more code:

CMainFrame::OnSize(int cx, int cy)
{
    GetWindowRect(&m_rectWindowRect);
}

void CMainFrame::OnWindowPosChanging(WINDOWPOS FAR* lpwndpos)
{
CMDIFrameWnd::OnWindowPosChanging(lpwndpos);
lpwndpos->flags |= SWP_NOMOVE;
// Setting tracker rectangle to initial  window size and position
lpwndpos->x = m_rectWindowRect.left;
lpwndpos->y = m_rectWindowRect.top;
lpwndpos->cx = m_rectWindowRect.right-m_rectWindowRect.left;
lpwndpos->cy = m_rectWindowRect.top-m_rectWindowRect.bottom;
}

Where m_rectWindowRect.top is CRect member of CMainFrame.
In this case user dont  see tracker rectangle dragging.
0
Maximize Your Threat Intelligence Reporting

Reporting is one of the most important and least talked about aspects of a world-class threat intelligence program. Here’s how to do it right.

 
LVL 3

Expert Comment

by:jaba
Comment Utility
Really, if onyxmedia wont window be moved,  he must disable or remove "Move" item  from sysmenu. It correct interface solution. BUT  ! Question  is :
============================
Is it possible to disable the move of the window without
hiding the titlebar (like patching GetMinMaxInfo for
disabling the resize of the window) ?
============================
And my answer is right in this context. I  really dont know anything about onyxmedia`s UI form, he  didnt ask anything about pretty UI view of his main window. May be his main window dont have sysmenu at all.
0
 
LVL 10

Expert Comment

by:RONSLOW
Comment Utility
We have BOTH answered the question correctly (you got in first though) - but in different ways.

"Is it possible to disable the move of the window without
hiding the titlebar"

I've disabled the user from being able to move the window.

You have disabled the window from moving if the user tries

The different is that I am stopping the cause, and you are stopping the effect.

As I said, for a nice user interface onyxmedia should probably combine the two solutions (as you have also now suggested because with your initial solution, the user can still try to move the window and gets an unexpected UI feedback and result).

Anyway - there is little point in us arguing over this.  We have presented our solutions and it is up to onyxmedia to award points for answers.

Perhaps (seeing we have both put some effort into this) he could put up a duplicate question (that I can answer with my solution) so we can BOTH get some points.

BTW: It is quite likely that he DOES have a system menu, because you can get it from right clicking in the title bar of an app.
0
 

Author Comment

by:onyxmedia
Comment Utility
Sorry ...
First, the program NEVER gone in the OnWindowPosChanging,
after your comment (This is MY solution ...), this function was
called, BUT the pointer lpwndpos is always NULL !!!
I had first a debug assertion failed, but after modifications:
if (lpwndpos != NULL) ...
the pointer NEVER get different than NULL !!!
I've tested the proposition from RONSLOW, and it works !!
Sorry jaba ... but thanx for your answer !
0
 
LVL 3

Expert Comment

by:jaba
Comment Utility
What operation system you using ? Vertion of compiler /MFC ? What kind of window ? Any more details ? I cant belive pointer alwas NULL, this part of code tested on reall window.
0
 
LVL 10

Expert Comment

by:RONSLOW
Comment Utility
Seems odd - - can you please post your OnWindowPosChanging code and also the message map entries.

PS: Can I put my solution up as an answer please if you are happy with it?

0
 

Author Comment

by:onyxmedia
Comment Utility
I'm running Windows NT Workstation 4.0, Visual C++ 5.0,
using MFC, my program is an SDI application and I have
implemented the OnWindowPosChanging in the CMainFrame
class ... Comment : The main view is a CFormView !

Here's the code :

MainFrm.h ---------------------------------------------------
protected:
      afx_msg void OnWindowPosChanging( WINDOWPOS FAR* lpwndpos );

MainFrm.cpp -----------------------------------------------
BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
      //{{AFX_MSG_MAP(CMainFrame)
      ON_MESSAGE(WM_WINDOWPOSCHANGING, OnWindowPosChanging)
      //}}AFX_MSG_MAP
END_MESSAGE_MAP()

void CMainFrame::OnWindowPosChanging( WINDOWPOS FAR* lpwndpos )
{
      CFrameWnd::OnWindowPosChanging(lpwndpos);
      WINDOWPOS *lpwp = lpwndpos;
//      lpwndpos->flags |= SWP_NOMOVE;
}

Note : I have made a VERY simple SDI application with
only THIS function in the MainFrame, and I have lauched
it in debug mode -> the pointer lpwp is ALWAYS NULL !

Comment to RONSLOW : Yes, you can put your solution as an
answer, I would be happy to grade it !
0
 
LVL 1

Expert Comment

by:IgorGrebnev
Comment Utility
Dear Onixmedia,
It is quite clear why you get the lpwndpos always NULL. The ON_MESSAGE macro should be associated with following prototype funciton:
LONG OnMyWindowPosChanging( UINT wParam, LONG lParam )
{WINDOWPOS FAR* lpwndpos = (WINDOWPOS FAR*)lParam;
  ...
}
If you wont to use CWnd::OnWindowPosChanging, then add
Add the ON_WM_WINDOWPOSCHANGING( ) macro to you messag map and DO  NOT you ON_MESSAGE.
yours, IGor

0
 
LVL 10

Accepted Solution

by:
RONSLOW earned 70 total points
Comment Utility
Here's how...

void CMainFrame::OnInitMenuPopup(CMenu* pMenu, UINT nIndex, BOOL bSysMenu)
{
if (bSysMenu && !m_bSysMenuInitialized) {
pMenu->RemoveMenu (SC_MOVE, MF_BYCOMMAND);
pMenu->RemoveMenu (SC_SIZE, MF_BYCOMMAND);
pMenu->RemoveMenu (SC_RESTORE, MF_BYCOMMAND);
pMenu->RemoveMenu (SC_MINIMIZE,MF_BYCOMMAND);
pMenu->RemoveMenu (SC_MAXIMIZE,MF_BYCOMMAND);
pMenu->RemoveMenu (SC_TASKLIST,MF_BYCOMMAND);
for (UINT i=0; i<pMenu->GetMenuItemCount(); i++) {
if (pMenu->GetMenuItemID(i) == 0) { // (if separator)
pMenu->RemoveMenu (i, MF_BYPOSITION);
continue;
}
}
m_bSysMenuInitialized = TRUE;
}
CFrameWnd::OnInitMenuPopup(pMenu, nIndex, bSysMenu);
}

void CMainFrame::OnNcLButtonDblClk(UINT nHitTest, CPoint point)
{
if (nHitTest==HTCAPTION) return;
CFrameWnd::OnNcLButtonDblClk(nHitTest, point);
}

void CMainFrame::OnSysCommand(UINT nID, LPARAM lParam)
{
switch (nID & 0x0fff0) {
case SC_MINIMIZE:
case SC_RESTORE:
case SC_NEXTWINDOW:
case SC_PREVWINDOW:
case SC_TASKLIST:
case SC_SIZE:
case SC_MOVE:
return; // (don't do anything)
}
CFrameWnd::OnSysCommand(nID, lParam);
}

BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
{
if (! CFrameWnd::PreCreateWindow(cs)) return FALSE;
cs.style &= ~WS_MINIMIZEBOX;
cs.style &= ~WS_MAXIMIZEBOX;
return TRUE;
}
 
PS: Shame you cannot split the points between jaba and myself.

0
 

Author Comment

by:onyxmedia
Comment Utility
Thanx !
0

Featured Post

Find Ransomware Secrets With All-Source Analysis

Ransomware has become a major concern for organizations; its prevalence has grown due to past successes achieved by threat actors. While each ransomware variant is different, we’ve seen some common tactics and trends used among the authors of the malware.

Join & Write a Comment

Here is how to use MFC's automatic Radio Button handling in your dialog boxes and forms.  Beginner programmers usually start with a OnClick handler for each radio button and that's just not the right way to go.  MFC has a very cool system for handli…
Introduction: Hints for the grid button.  Nested classes, templated collections.  Squash that darned bug! Continuing from the sixth article about sudoku.   Open the project in visual studio. First we will finish with the SUD_SETVALUE messa…
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.
Sending a Secure fax is easy with eFax Corporate (http://www.enterprise.efax.com). First, Just open a new email message.  In the To field, type your recipient's fax number @efaxsend.com. You can even send a secure international fax — just include t…

762 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

9 Experts available now in Live!

Get 1:1 Help Now