home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Troubleshooting Netware Systems
/
CSTRIAL0196.BIN
/
attach
/
msj
/
v10n08
/
sketchsc.exe
/
MYWIN.H
< prev
next >
Wrap
C/C++ Source or Header
|
1995-08-01
|
6KB
|
180 lines
//-----------------------------------------------------------------------
// MYWIN.H: Various Windows support classes
//-----------------------------------------------------------------------
#ifndef MYWIN_H__
#define MYWIN_H__
#ifdef DEBUG
#define D(x) x
#else
#define D(x) /*empty*/
#endif
//-----------------------------------------------------------------------
// The mapping_mode is a convenience. It is intended for use ONLY by the
// device class. You set the mapping mode anywhere in your program
// either by creating an object like this:
//
// mapping_mode m( MM_TEXT );
//
// or executing a cast instruction somewhere in your program:
//
// mapping_mode( MM_TEXT );
//
// You can do this only once. So it's best to do it as a global variable
// or with a call in your applications InitInstance() function.
//
// I've encapsulated the mapping mode into a class (as compared to using
// a global variable) to guarantee that it won't be used without having
// been set and that it won't change after being set. Keeps everbody
// honest. For example, the following code appears in the device
// implemenation:
//
// SetMapMode( mapping_mode() );
//
// The "mapping_mode()" is a cast that creates a mapping-mode object
// (which is actually of zero size since it's only field is static).
// The compiler then converts that object into an int, using
// mapping_mode::operator int(), which returns the actual mapping mode.
// It does some data validition first, though, and throws a
// mapping_mode::error object if the mode hasn't been set yet.
// All this is done inline, with the error checking removed when not
// debugging, so is no less efficient than a direct access of a global
// variable.
class mapping_mode
{
static int mode;
enum { MM_NONE = MM_MAX+1 }; // MM_MAX defined by Windows
void check_valid( void );
public:
class error{};
mapping_mode( UINT init_mode );
private:
friend class device;
friend class rect_update;
mapping_mode( void ){}
operator int( void );
};
//-----------------------------------------------------------------------
inline mapping_mode::mapping_mode( UINT init_mode )
{
D( if( mode != MM_NONE ) )// Can be set only once.
D( throw error(); )
mode = init_mode ;
}
//-----------------------------------------------------------------------
inline mapping_mode::operator int( )
{
D( if( mode == MM_NONE ) )
D( throw error(); )
return mode;
}
//=======================================================================
// My variant on a device context. Automatically maps into and out
// of the current mapping modes. Create from a window to get the
// equivalent of a CClientDC and from a CDC to get a auto-mapping
// device context. The original device context is not released in
// this last case (ie, I'm assuming that you got it from an existing
// CDC).
//
// the device also adds to the windows DC by supporting
// the notion of a puts() function. It keeps a document-relative
// text cursor and puts at that location. The line height is
// contolled by the current font.
//
// dc->puts( const CString &str );
// dc-set_text_cursor( const CPoint &location );
// Use puts like this to get printf-style functionality:
//
// CString s;
// dc->puts( s.Format("fmt",args) );
//
// The function returns the current cursor location after the print.
// TabbedTextOut() is used to print the buffer, so use SetTextAlign,
// etc to control placement. The position is controled by an
// internal cursor and is advanced to the next line automatically
// after every puts() call. Use set_text_cursor() to set a text
// position (in logical units) to be used by the next puts() call.
// The 'y' coordinate sticks on, so all subsequent lines will be
// offset if set_text_cursor presents a nonzero y coordinate.
// Tabs are 8-space tabs, starting at the far left of the line,
// where a "space" is the average character width.
class device : public CDC
{
const CWnd *owner;
CPoint cursor; // puts() cursor
CRect bounding; // bounding rectangle if this is a CPaintDC
protected:
virtual void prepare( void );
public:
virtual
~device( void );
device( const CWnd *win );
device( const CDC *dc );
void set_up_scrolling( CSize document_size );
const CPoint &puts ( const CString &str );
void set_text_cursor( const CPoint &location );
void invalidate_rect( CRect invalid_region,
int erase_background = TRUE );
private: friend class rect_client;
CRect *get_client_rect( CRect *r ) const;
};
//-----------------------------------------------------------------------
inline void device::set_text_cursor( const CPoint &location )
{
cursor = location;
}
//=======================================================================
class rect_client: public CRect
{
public:
rect_client( const device &dc )
{
dc.get_client_rect( this );
}
};
//=======================================================================
class rect_clip: public CRect
{
public:
rect_clip( const device &dc )
{
dc.GetClipBox( this );
}
};
//=======================================================================
class rect_update: public CRect
{
public:
rect_update( CWnd *win )
{
win->GetUpdateRect( this, FALSE );
if( !IsRectEmpty() )
{
DWORD winstyle = GetClassLong(win->m_hWnd, GWL_STYLE);
if( !((winstyle & CS_OWNDC) && (mapping_mode()==MM_TEXT)) )
{
device dc( win );
dc.DPtoLP( this );
}
}
}
};
#endif // MYWIN_H__