Link to home
Start Free TrialLog in
Avatar of Knallar
KnallarFlag for Germany

asked on

Who has an answer? (desperately needed)

Hi!

I am porting an application from Unix to NT... With Unix XView you have a client area called canvas. The canvas is the area where you can paint on.

So, how do I transform a canvas to NT? I would like to have a CFrameWnd and a dialog inside this frame (modal and unsizeable at the right border) and an area inside this frame (frame minus dialog), where I can paint on.

Now I use the frame itself, but that causes the annoying effect, that you can paint outside the allowed area (over the dialog)...

So what do I need?  A view to paint on? But it should be no MDI application and also I will not use any document...
(it's old software and the portation has to be done very quickly)...

Thanks for any advice...
Avatar of psdavis
psdavis
Flag of United States of America image

You can paint in a dialog just like any other window.  When painting, store your information to draw in a CBitmap or more preferrably in a DIB (see DIBLOOK sample for base code).  Once you have a DIB (for example) use the SetDIBitsToDevice with the dialog's coordinates (use GetClientRect for them) to draw it within the boundaries.  If you need to stretch, use StretchDIBits.

If you want to use a CBitmap, you'll want BitBlt or StretchBlt.  Both will take parameters on the size.

Good luck and tell us how things are going.

Phillip
Avatar of Knallar

ASKER

That's not what I asked... sorry...

Didn't want to paint inside a dialog..
I need something like this

---------------------------------------------------
|                                               |x|
---------------------------------------------------
|                                        |        |
|                                        |        |
|                                        |        |
|                                        |        |
|                                        |        |
|                                        |        |
|                                        |        |
|                                        |        |
|                                        |        |
|-------------------------------------------------|
     ^                                    ^
     this is the client area           that should be
     to be painted in                 the unmoveable, unsizable
                                          dialog

The CFrameWnd is maximized the dialog stucks on the right side and I need something that represents the client area to the left (without the dialog)... something like in UNIX the canvas...

And I don't exactly know... what!  A CView?
But I can't use a MDI application, because there's just one window!

That's the point...






If you are painting, than you must be capturing the mouse position. You also can decide not to paint at a particular position. In your WM_MOUSEMOVE, create code to stop drawing when over dialog.
Any reason why you are using a CDialog? What about using a control bar?
If you use a view, you will still able to draw outside of your client area. You still must create code for deciding when not to paint.

Avatar of Knallar

ASKER

No... does't satisfy me...

If I use a CDialog or CControlBar does not matter here...

Capturing the mouse event is nonsense...

Once again: I want the client area inside the frame with a specific size!!! That is: the frame minus the dialog...

Nothing else...
Avatar of snoegler
snoegler

Okay, two possibilities:

a) In your paint function you can exclude a rectangle from the clipping region of your CPaintDC:

xxx::OnPaint()
{
  CPaintDC dc(this);
  CRect rcClient,rcDialog;

  GetClientRect(&rcClient);
  GetWindowRect(&rcDialog);
  ScreenToClient(&rcDialog);
  // save DC state(don't think this is needed - just for safety)
  // Now the important part:
  int sdc=dc.SaveDC();
  dc.ExcludeClipRect(&rcDialog); // Exclude the dialog rectangle from the clipping region
 
  .... // perform your drawing
  dc.RestoreDC(sdc); // restore DC
}

b) Use the Doc/View architecture, create a static split window, with the paint view to the left
     and the dialog view to the right. That will work, but i think you'll have to redesign your
     application a little bit.

But i think a) is more useful to you, because you just restrict the painting area to the 'real' client
rectangle.
Hope this helped :)

Hmm.. Kinda unclear, but let's try...

Question: Do you want to draw in the background frame area of the CFrameWnd? or would you rather do it in a CView?

Since you want the dialog to be unmovable and unresizeable, not much point of having the dialog in the first place.  

What I am thinking is: Why not make yourself a SDI application.  In the main CView, draw the image area in the left hand side.  Add your controls to the right hand side like your dialog.

Whatcha think?

Phillip
Avatar of Knallar

ASKER

To snoegler....

I know, that I could exclude the rectangle... would be something like the mousemoving-answer... doesn't really satisfy me, also.

hmmm maybe I should point more onto the canvas-problem....

What I need is a kind of substitude for the canvas....

I need a class (MyCanvas) which is able to capture all events and has the frame as a father...

So only a drawing window with a specific size is needed... and only one! (without a menu or minmax-buttons) ...

This class should represent the client-area and should be used in different applications (all SDI-like)... BUT WITHOUT any document...

Now, what I exactly need is:

How do you implement that  (i'm new in MFC)
Now I use as the the frame a CFrameWnd (do I need a CMDIFrame) with a single CView?
How does the frame creates the view?  (only saw in one example, that the views are connected to the doc (which I don't need ;) and automaticly created by CXXXDocTemplate...

Can I use that and kick away the document?

PUUUHH

Okay, you don't like it ...
Another way:

Create a new class (subclass 'generic CWnd'), put this CWnd into your CFrameWnd
- i think you know how - and then put your painting & capture functions into this class.
Within this classes OnPaint() function, you won't be able to draw out of the window's client
rectangle. Every mouse event and so in is passed to this window as well - and i think
then you've got your canvas :)

Of course you have to handle your CFrameWnd's WM_SIZE message to resize&reposition
this window, so that its place stays the same ...
Avatar of Knallar

ASKER

Create a new class (subclass 'generic CWnd'), put this CWnd into your CFrameWnd

no, I don't exactly know how...

with CDocTemplate  or just inside the create function of CFrameWnd or how?

And: there's a CreateClient- method from the CMDIFrameWnd class..
but there's noone in CFrameWnd...

so I don't exactly know how...
If you do it like this, you don't need the Doc-View architecture.
How to create a simple CFrameWnd-application(without doc-view):

1) Create a SDI app, leave all options on default
2) Remove the doc and view source files (myappview.cpp, myappdoc.cpp) from your project
3) Open your CWinApp '.cpp' file, remove the #include statements for the "myappview.h" and
"myappdoc.h"
4)  Select the InitInstance() method
5) Remove everything between the line 'ParseCommandLine(cmdInfo)' and
   'return TRUE';
6) Insert the following statements below 'ParseCommandLine(cmdInfo)':
  CFrameWnd *pMainWnd;
  pMainWnd=(CFrameWnd*)(RUNTIME_CLASS(CMainFrame)->CreateObject());
  pMainWnd->LoadFrame(IDR_MAINFRAME);
  m_pMainWnd=pMainWnd; // init main window member variable of CWinApp
  pMainWnd->ShowWindow(SW_SHOW);

After this, you've got only three classes in your project:
Your CWinApp derivate, your CMainFrame(), and your CAboutDlg().
The menu stays the same, also the tool&statusbars.
Avatar of Knallar

ASKER

Tada!

But I have no view!
If I use your comment, I have exactly the same as now...
;)
I have a frame and my dialog...
I thougt we've came to the point that I should use a CWnd for the "canvas"... inserted somehow into the frame...

And the question was: how to "somehow"?


BTW: Thank you so far...
For your CWnd-derivate:

1) Open ClassWizard, choose 'Add class'/'New...'
2) Give it a name, for example 'CPaintWnd'
3) Select 'generic CWnd' as base class
4) Add the message handlers you need, for example WM_PAINT, WM_CREATE,
    WM_MOUSEMOVE and so on.

To initalize this CWnd and add it to your CMainFrame:

1) Right-click on CMainFrame, 'Add variable' (for example m_wndPaint)
2) Add a variable of your CWnd type
3) Insert a "#include paintwnd.h" on top of your mainfrm.h

4) Select 'CMainFrame::OnCreate()'
5) Insert the following directly before the 'return 0;' statement:

m_wndPaint.Create(NULL,"Paint window",WS_CHILD|WS_VISIBLE,CRect(0,0,0,0),
  this,(UINT)IDC_STATIC);
m_wndPaint.ShowWindow(SW_SHOW);

6) Add a 'WM_SIZE' message handler to your CMainFrame
7) Insert there the following lines(After the '// TODO: xxx' comment)

  CRect rcClient,rcDialog,rcPaint;
  GetClientRect(&rcClient);
  rcDialog=rcClient;
  rcPaint=rcClient;
  rcDialog.left=rcClient.right-100; // 100 pixels width for your CDialog
  rcPaint.right=rcClient.right-100; // the rest for your CPaintWnd
  m_myDialog.MoveWindow(&rcDialog);
  m_wndPaint.MoveWindow(&rcPaint);

I don't know how you implemented your dialog - i just guessed above that you have some
member variable of your CMainFrame which refers to it.
If you used a CDialogBar, then it should look like this:

  CRect rcClient;
  GetClientRect(&rcClient);
  m_wndPaint.MoveWindow(&rcClient);
Avatar of Knallar

ASKER

Tada!

But I have no view!
If I use your comment, I have exactly the same as now...
;)
I have a frame and my dialog...
I thougt we've came to the point that I should use a CWnd for the "canvas"... inserted somehow into the frame...

And the question was: how to "somehow"?


BTW: Thank you so far...
Avatar of Knallar

ASKER

Oki Dukki... Mr. Jones...

I give it a try... ;)
Avatar of Knallar

ASKER

I've tried it...
First in my source and as it doesn't work, in a testapplication->
fails also!

Would you be so kind and send me a correct project to
ralf.allar@wup.de

or I sent you my little project...

(I would increase the points)  ;)


Avatar of Knallar

ASKER

here is my source:

//----- mainframe.h


#include "PaintWnd.h"

class CMainFrame : public CFrameWnd
{
protected: // create from serialization only
      CMainFrame();
      DECLARE_DYNCREATE(CMainFrame)

// Attributes
public:
      CPaintWnd m_wndPaint;
// Operations
public:

// Overrides
      // ClassWizard generated virtual function overrides
      //{{AFX_VIRTUAL(CMainFrame)
      virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
      //}}AFX_VIRTUAL

// Implementation
public:
      virtual ~CMainFrame();
#ifdef _DEBUG
      virtual void AssertValid() const;
      virtual void Dump(CDumpContext& dc) const;
#endif

// Generated message map functions
protected:
      //{{AFX_MSG(CMainFrame)
      afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
      afx_msg void OnSize(UINT nType, int cx, int cy);
      //}}AFX_MSG
      DECLARE_MESSAGE_MAP()
};



///---paintwnd.h

/////////////////////////////////////////////////////////////////////////////
// CPaintWnd window

class CPaintWnd : public CWnd
{
// Construction
public:
      CPaintWnd();

// Attributes
public:

// Operations
public:

// Overrides
      // ClassWizard generated virtual function overrides
      //{{AFX_VIRTUAL(CPaintWnd)
      //}}AFX_VIRTUAL

// Implementation
public:
      virtual ~CPaintWnd();

      // Generated message map functions
protected:
      //{{AFX_MSG(CPaintWnd)
      afx_msg void OnPaint();
      afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
      afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
      //}}AFX_MSG
      DECLARE_MESSAGE_MAP()
};

/////////////////////////////////////////



//  test2.h

#include "resource.h"       // main symbols

/////////////////////////////////////////////////////////////////////////////
// CTest2App:
// See Test2.cpp for the implementation of this class
//

class CTest2App : public CWinApp
{
public:
      CTest2App();

// Overrides
      // ClassWizard generated virtual function overrides
      //{{AFX_VIRTUAL(CTest2App)
      public:
      virtual BOOL InitInstance();
      //}}AFX_VIRTUAL

// Implementation

      //{{AFX_MSG(CTest2App)
      afx_msg void OnAppAbout();
            // NOTE - the ClassWizard will add and remove member functions here.
            //    DO NOT EDIT what you see in these blocks of generated code !
      //}}AFX_MSG
      DECLARE_MESSAGE_MAP()
};



//  mainframe.cpp
#include "stdafx.h"
#include "Test2.h"

#include "MainFrm.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CMainFrame

IMPLEMENT_DYNCREATE(CMainFrame, CFrameWnd)

BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
      //{{AFX_MSG_MAP(CMainFrame)
      ON_WM_CREATE()
      ON_WM_SIZE()
      //}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CMainFrame construction/destruction

CMainFrame::CMainFrame()
{
      // TODO: add member initialization code here
      
}

CMainFrame::~CMainFrame()
{
}

BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
{
      // TODO: Modify the Window class or styles here by modifying
      //  the CREATESTRUCT cs

      return CFrameWnd::PreCreateWindow(cs);
}

/////////////////////////////////////////////////////////////////////////////
// CMainFrame diagnostics

#ifdef _DEBUG
void CMainFrame::AssertValid() const
{
      CFrameWnd::AssertValid();
}

void CMainFrame::Dump(CDumpContext& dc) const
{
      CFrameWnd::Dump(dc);
}

#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CMainFrame message handlers

int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
      if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
            return -1;
      
      // TODO: Add your specialized creation code here
      m_wndPaint.Create(NULL,"Paint window",WS_CHILD|WS_VISIBLE,CRect(10,10,100,100),
  this,(UINT)IDC_STATIC);
m_wndPaint.ShowWindow(SW_SHOW);

      return 0;
}

void CMainFrame::OnSize(UINT nType, int cx, int cy)
{
      CFrameWnd::OnSize(nType, cx, cy);
      
      // TODO: Add your message handler code here
      CRect rcClient,rcPaint;
  GetClientRect(&rcClient);
  rcPaint=rcClient;
  rcPaint.right=rcClient.right-100; // the rest for your CPaintWnd
  m_wndPaint.MoveWindow(&rcPaint);
}




// ---- paintwnd.cpp

#include "stdafx.h"
#include "Test2.h"
#include "PaintWnd.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CPaintWnd

CPaintWnd::CPaintWnd()
{
}

CPaintWnd::~CPaintWnd()
{
}


BEGIN_MESSAGE_MAP(CPaintWnd, CWnd)
      //{{AFX_MSG_MAP(CPaintWnd)
      ON_WM_PAINT()
      ON_WM_CREATE()
      ON_WM_LBUTTONDOWN()
      //}}AFX_MSG_MAP
END_MESSAGE_MAP()


/////////////////////////////////////////////////////////////////////////////
// CPaintWnd message handlers

void CPaintWnd::OnPaint()
{
      CPaintDC dc(this); // device context for painting
      
      // TODO: Add your message handler code here
      
      // Do not call CWnd::OnPaint() for painting messages
}

int CPaintWnd::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
      if (CWnd::OnCreate(lpCreateStruct) == -1)
            return -1;
      
      // TODO: Add your specialized creation code here
      
      return 0;
}

void CPaintWnd::OnLButtonDown(UINT nFlags, CPoint point)
{
      // TODO: Add your message handler code here and/or call default
      
      CWnd::OnLButtonDown(nFlags, point);
}





// test2.cpp

#include "stdafx.h"
#include "Test2.h"

#include "MainFrm.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CTest2App

BEGIN_MESSAGE_MAP(CTest2App, CWinApp)
      //{{AFX_MSG_MAP(CTest2App)
      ON_COMMAND(ID_APP_ABOUT, OnAppAbout)
            // NOTE - the ClassWizard will add and remove mapping macros here.
            //    DO NOT EDIT what you see in these blocks of generated code!
      //}}AFX_MSG_MAP
      // Standard file based document commands
      ON_COMMAND(ID_FILE_NEW, CWinApp::OnFileNew)
      ON_COMMAND(ID_FILE_OPEN, CWinApp::OnFileOpen)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CTest2App construction

CTest2App::CTest2App()
{
      // TODO: add construction code here,
      // Place all significant initialization in InitInstance
}

/////////////////////////////////////////////////////////////////////////////
// The one and only CTest2App object

CTest2App theApp;

/////////////////////////////////////////////////////////////////////////////
// CTest2App initialization

BOOL CTest2App::InitInstance()
{
      // Standard initialization
      // If you are not using these features and wish to reduce the size
      //  of your final executable, you should remove from the following
      //  the specific initialization routines you do not need.

#ifdef _AFXDLL
      Enable3dControls();                  // Call this when using MFC in a shared DLL
#else
      Enable3dControlsStatic();      // Call this when linking to MFC statically
#endif

      // Change the registry key under which our settings are stored.
      // You should modify this string to be something appropriate
      // such as the name of your company or organization.
      SetRegistryKey(_T("Local AppWizard-Generated Applications"));

      LoadStdProfileSettings();  // Load standard INI file options (including MRU)

      // Register the application's document templates.  Document templates
      //  serve as the connection between documents, frame windows and views.
/*
      CSingleDocTemplate* pDocTemplate;
      pDocTemplate = new CSingleDocTemplate(
            IDR_MAINFRAME,
            RUNTIME_CLASS(CTest2Doc),
            RUNTIME_CLASS(CMainFrame),       // main SDI frame window
            RUNTIME_CLASS(CTest2View));
      AddDocTemplate(pDocTemplate);
*/
      // Parse command line for standard shell commands, DDE, file open
      CCommandLineInfo cmdInfo;
      ParseCommandLine(cmdInfo);

      CFrameWnd *pMainWnd;
  pMainWnd=(CFrameWnd*)(RUNTIME_CLASS(CMainFrame)->CreateObject());
  pMainWnd->LoadFrame(IDR_MAINFRAME);
  m_pMainWnd=pMainWnd; // init main window member variable of CWinApp
  pMainWnd->ShowWindow(SW_SHOW);



/*
      // Dispatch commands specified on the command line
      if (!ProcessShellCommand(cmdInfo))
            return FALSE;

      // The one and only window has been initialized, so show and update it.
      m_pMainWnd->ShowWindow(SW_SHOW);
      m_pMainWnd->UpdateWindow();
*/
      return TRUE;
}
Avatar of Knallar

ASKER

Adjusted points to 300
Avatar of Knallar

ASKER

if you run that app... you get the messages like onlmbuttondown... in the child window...
but the child does not appear inside the frame

the "canvas" respectively the client area (the child) is a big as the frame...

*grmbl*

Avatar of Knallar

ASKER

if you run that app... you get the messages like onlmbuttondown... in the child window...
but the child does not appear inside the frame

the "canvas" respectively the client area (the child) is a big as the frame...

*grmbl*

Okay, i'll make me a big cup of coffee and try to get something like you want to work :)
Avatar of Knallar

ASKER

providing a big 'a', if it runs...
i've puzzled 5 hours on that, yet...
Okay, i think i got something ... Hope it's useful to you.
It uses the Doc/View architecture (but it's not necessary to use it as you'll see, it can easily be
converted to a simple CMainFrame), a CDialogPane (which is a CDialog) and a CPaintWnd
(generic CWnd).

Here's the download location:
http://absd.hypermart.net/media/demo.zip (i used PkWare's winzip)
caution: the URL is case sensitive

Hope it helps (again) :)

Avatar of Knallar

ASKER

O.K.... thank you so far...

meanwhile... I'm sitting on another problem (porting is not only fun)

I'll try to understand it tomorrow or on monday...

After a correction of the makefile it ran... cool


Once again... big applause and the grade will follow

;)
Avatar of Knallar

ASKER

Hi snoegler...

just flew over the code and noticed, that it needs a document...
how can I handle the view without a document?

I can't use this construct:
pDocTemplate = new CSingleDocTemplate(
            IDR_MAINFRAME,
            RUNTIME_CLASS(CGraphDoc),
            RUNTIME_CLASS(CMainFrame),  
            RUNTIME_CLASS(CGraphView));

Just kicking it out, won't work...
Please give me some time to answer this('til tomorrow) ....
Try this it may solve your problem.

Change the dialog style to child in the properties of the dialog in the resource editor.
and change the border to none just below the style.


And crete the dialog in the frame window, and in OnSize handler of frame window move the dialog to fit the entire client area of frame.

Avatar of Knallar

ASKER

Sudhirbrat... that is not what I asked...
sorry....
Why don't you make your dialog a toolbar attached to the right border of the frame. In this case your frames client area is adjusted.
Dear brother/sister,

Please try the following by using message reflection.
for more info please see vc++ help

what colour you want you can write code under the following function.

::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)

any doubts, send me mail.

with love,
Bhavani P Polimetla
bhavani_73@hotmail.com
Avatar of Knallar

ASKER

That is a joke, isn't it?
if already figured it out..
ASKER CERTIFIED SOLUTION
Avatar of graber
graber
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial