summaryrefslogtreecommitdiffstats
path: root/mmc_updater/depends
diff options
context:
space:
mode:
authorPetr Mrázek <peterix@gmail.com>2013-12-02 00:55:24 +0100
committerPetr Mrázek <peterix@gmail.com>2013-12-02 00:55:24 +0100
commit6aa9bd0f77dcb5128167fae62e32aa5252fe85c6 (patch)
tree632994a61888929af9289927d338bd19a2b3f32c /mmc_updater/depends
parent613699b3626aea750093ab7eaaeccaa28c0e87c6 (diff)
downloadMultiMC-6aa9bd0f77dcb5128167fae62e32aa5252fe85c6.tar
MultiMC-6aa9bd0f77dcb5128167fae62e32aa5252fe85c6.tar.gz
MultiMC-6aa9bd0f77dcb5128167fae62e32aa5252fe85c6.tar.lz
MultiMC-6aa9bd0f77dcb5128167fae62e32aa5252fe85c6.tar.xz
MultiMC-6aa9bd0f77dcb5128167fae62e32aa5252fe85c6.zip
Renew the updater branch
Now with some actual consensus on what the updater will do!
Diffstat (limited to 'mmc_updater/depends')
-rw-r--r--mmc_updater/depends/AnyOption/CMakeLists.txt9
-rw-r--r--mmc_updater/depends/AnyOption/README16
-rw-r--r--mmc_updater/depends/AnyOption/anyoption.cpp1176
-rw-r--r--mmc_updater/depends/AnyOption/anyoption.h270
-rw-r--r--mmc_updater/depends/tinyxml/CMakeLists.txt24
-rw-r--r--mmc_updater/depends/tinyxml/readme.txt530
-rw-r--r--mmc_updater/depends/tinyxml/tinystr.cpp111
-rw-r--r--mmc_updater/depends/tinyxml/tinystr.h305
-rw-r--r--mmc_updater/depends/tinyxml/tinyxml.cpp1886
-rw-r--r--mmc_updater/depends/tinyxml/tinyxml.h1805
-rw-r--r--mmc_updater/depends/tinyxml/tinyxmlerror.cpp52
-rw-r--r--mmc_updater/depends/tinyxml/tinyxmlparser.cpp1638
-rw-r--r--mmc_updater/depends/win32cpp/controls.h1074
-rw-r--r--mmc_updater/depends/win32cpp/copyright.txt33
-rw-r--r--mmc_updater/depends/win32cpp/cstring.h905
-rw-r--r--mmc_updater/depends/win32cpp/default_resource.h94
-rw-r--r--mmc_updater/depends/win32cpp/default_resource.rc250
-rw-r--r--mmc_updater/depends/win32cpp/dialog.h876
-rw-r--r--mmc_updater/depends/win32cpp/docking.h4214
-rw-r--r--mmc_updater/depends/win32cpp/file.h392
-rw-r--r--mmc_updater/depends/win32cpp/frame.h3303
-rw-r--r--mmc_updater/depends/win32cpp/gdi.h3944
-rw-r--r--mmc_updater/depends/win32cpp/info.txt205
-rw-r--r--mmc_updater/depends/win32cpp/listview.h867
-rw-r--r--mmc_updater/depends/win32cpp/mdi.h783
-rw-r--r--mmc_updater/depends/win32cpp/menu.h600
-rw-r--r--mmc_updater/depends/win32cpp/propertysheet.h960
-rw-r--r--mmc_updater/depends/win32cpp/rebar.h709
-rw-r--r--mmc_updater/depends/win32cpp/release notes.txt116
-rw-r--r--mmc_updater/depends/win32cpp/ribbon.h527
-rw-r--r--mmc_updater/depends/win32cpp/shared_ptr.h199
-rw-r--r--mmc_updater/depends/win32cpp/socket.h778
-rw-r--r--mmc_updater/depends/win32cpp/statusbar.h226
-rw-r--r--mmc_updater/depends/win32cpp/stdcontrols.h1000
-rw-r--r--mmc_updater/depends/win32cpp/tab.h1658
-rw-r--r--mmc_updater/depends/win32cpp/taskdialog.h811
-rw-r--r--mmc_updater/depends/win32cpp/thread.h241
-rw-r--r--mmc_updater/depends/win32cpp/toolbar.h1361
-rw-r--r--mmc_updater/depends/win32cpp/treeview.h624
-rw-r--r--mmc_updater/depends/win32cpp/wceframe.h420
-rw-r--r--mmc_updater/depends/win32cpp/wcestddef.h58
-rw-r--r--mmc_updater/depends/win32cpp/webbrowser.h760
-rw-r--r--mmc_updater/depends/win32cpp/wincore.h2977
-rw-r--r--mmc_updater/depends/win32cpp/winutils.h649
44 files changed, 39436 insertions, 0 deletions
diff --git a/mmc_updater/depends/AnyOption/CMakeLists.txt b/mmc_updater/depends/AnyOption/CMakeLists.txt
new file mode 100644
index 00000000..fdfd6076
--- /dev/null
+++ b/mmc_updater/depends/AnyOption/CMakeLists.txt
@@ -0,0 +1,9 @@
+project(AnyOption)
+
+cmake_minimum_required(VERSION 2.6)
+
+add_library(anyoption
+ anyoption.cpp
+ anyoption.h
+)
+
diff --git a/mmc_updater/depends/AnyOption/README b/mmc_updater/depends/AnyOption/README
new file mode 100644
index 00000000..d91d6851
--- /dev/null
+++ b/mmc_updater/depends/AnyOption/README
@@ -0,0 +1,16 @@
+
+http://www.hackorama.com/anyoption/
+
+AnyOption is a C++ class for easy parsing of complex commandline options. It also parses options from a rsourcefile in option value pair format.
+
+AnyOption implements the traditional POSIX style character options ( -n ) as well as the newer GNU style long options ( --name ). Or you can use a simpler long option version ( -name ) by asking to ignore the POSIX style options.
+
+AnyOption supports the traditional UNIX resourcefile syntax of, any line starting with "#" is a comment and the value pairs use ":" as a delimiter.
+
+An option which expects a value is considered as an option value pair, while options without a value are considered flags.
+
+Please read the header file for the documented public interface, and demo.cpp for an example of how easy it is to use AnyOption.
+
+August 2004, added bug-fixes, and updates send by Michael Peters of Sandia Lab.
+September 2006, fix from Boyan Asenov for a bug in mixing up option type indexes.
+July 2011, fix from Min KJ and Costantino G for string allocation.
diff --git a/mmc_updater/depends/AnyOption/anyoption.cpp b/mmc_updater/depends/AnyOption/anyoption.cpp
new file mode 100644
index 00000000..6792fe3e
--- /dev/null
+++ b/mmc_updater/depends/AnyOption/anyoption.cpp
@@ -0,0 +1,1176 @@
+/*
+ * AnyOption 1.3
+ *
+ * kishan at hackorama dot com www.hackorama.com JULY 2001
+ *
+ * + Acts as a common facade class for reading
+ * commandline options as well as options from
+ * an optionfile with delimited type value pairs
+ *
+ * + Handles the POSIX style single character options ( -w )
+ * as well as the newer GNU long options ( --width )
+ *
+ * + The option file assumes the traditional format of
+ * first character based comment lines and type value
+ * pairs with a delimiter , and flags which are not pairs
+ *
+ * # this is a coment
+ * # next line is an option value pair
+ * width : 100
+ * # next line is a flag
+ * noimages
+ *
+ * + Supports printing out Help and Usage
+ *
+ * + Why not just use getopt() ?
+ *
+ * getopt() Its a POSIX standard not part of ANSI-C.
+ * So it may not be available on platforms like Windows.
+ *
+ * + Why it is so long ?
+ *
+ * The actual code which does command line parsing
+ * and option file parsing are done in few methods.
+ * Most of the extra code are for providing a flexible
+ * common public interface to both a resourcefile and
+ * and command line supporting POSIX style and
+ * GNU long option as well as mixing of both.
+ *
+ * + Please see "anyoption.h" for public method descriptions
+ *
+ */
+
+/* Updated Auguest 2004
+ * Fix from Michael D Peters (mpeters at sandia.gov)
+ * to remove static local variables, allowing multiple instantiations
+ * of the reader (for using multiple configuration files). There is
+ * an error in the destructor when using multiple instances, so you
+ * cannot delete your objects (it will crash), but not calling the
+ * destructor only introduces a small memory leak, so I
+ * have not bothered tracking it down.
+ *
+ * Also updated to use modern C++ style headers, rather than
+ * depricated iostream.h (it was causing my compiler problems)
+*/
+
+/*
+ * Updated September 2006
+ * Fix from Boyan Asenov for a bug in mixing up option indexes
+ * leading to exception when mixing different options types
+ */
+
+#include "anyoption.h"
+
+#include <string.h>
+
+AnyOption::AnyOption()
+{
+ init();
+}
+
+AnyOption::AnyOption(int maxopt)
+{
+ init( maxopt , maxopt );
+}
+
+AnyOption::AnyOption(int maxopt, int maxcharopt)
+{
+ init( maxopt , maxcharopt );
+}
+
+AnyOption::~AnyOption()
+{
+ if( mem_allocated )
+ cleanup();
+}
+
+void
+AnyOption::init()
+{
+ init( DEFAULT_MAXOPTS , DEFAULT_MAXOPTS );
+}
+
+void
+AnyOption::init(int maxopt, int maxcharopt )
+{
+
+ max_options = maxopt;
+ max_char_options = maxcharopt;
+ max_usage_lines = DEFAULT_MAXUSAGE;
+ usage_lines = 0 ;
+ argc = 0;
+ argv = NULL;
+ posix_style = true;
+ verbose = false;
+ filename = NULL;
+ appname = NULL;
+ option_counter = 0;
+ optchar_counter = 0;
+ new_argv = NULL;
+ new_argc = 0 ;
+ max_legal_args = 0 ;
+ command_set = false;
+ file_set = false;
+ values = NULL;
+ g_value_counter = 0;
+ mem_allocated = false;
+ command_set = false;
+ file_set = false;
+ opt_prefix_char = '-';
+ file_delimiter_char = ':';
+ file_comment_char = '#';
+ equalsign = '=';
+ comment = '#' ;
+ delimiter = ':' ;
+ endofline = '\n';
+ whitespace = ' ' ;
+ nullterminate = '\0';
+ set = false;
+ once = true;
+ hasoptions = false;
+ autousage = false;
+
+ strcpy( long_opt_prefix , "--" );
+
+ if( alloc() == false ){
+ cout << endl << "OPTIONS ERROR : Failed allocating memory" ;
+ cout << endl ;
+ cout << "Exiting." << endl ;
+ exit (0);
+ }
+}
+
+bool
+AnyOption::alloc()
+{
+ int i = 0 ;
+ int size = 0 ;
+
+ if( mem_allocated )
+ return true;
+
+ size = (max_options+1) * sizeof(const char*);
+ options = (const char**)malloc( size );
+ optiontype = (int*) malloc( (max_options+1)*sizeof(int) );
+ optionindex = (int*) malloc( (max_options+1)*sizeof(int) );
+ if( options == NULL || optiontype == NULL || optionindex == NULL )
+ return false;
+ else
+ mem_allocated = true;
+ for( i = 0 ; i < max_options ; i++ ){
+ options[i] = NULL;
+ optiontype[i] = 0 ;
+ optionindex[i] = -1 ;
+ }
+ optionchars = (char*) malloc( (max_char_options+1)*sizeof(char) );
+ optchartype = (int*) malloc( (max_char_options+1)*sizeof(int) );
+ optcharindex = (int*) malloc( (max_char_options+1)*sizeof(int) );
+ if( optionchars == NULL ||
+ optchartype == NULL ||
+ optcharindex == NULL )
+ {
+ mem_allocated = false;
+ return false;
+ }
+ for( i = 0 ; i < max_char_options ; i++ ){
+ optionchars[i] = '0';
+ optchartype[i] = 0 ;
+ optcharindex[i] = -1 ;
+ }
+
+ size = (max_usage_lines+1) * sizeof(const char*) ;
+ usage = (const char**) malloc( size );
+
+ if( usage == NULL ){
+ mem_allocated = false;
+ return false;
+ }
+ for( i = 0 ; i < max_usage_lines ; i++ )
+ usage[i] = NULL;
+
+ return true;
+}
+
+bool
+AnyOption::doubleOptStorage()
+{
+ options = (const char**)realloc( options,
+ ((2*max_options)+1) * sizeof( const char*) );
+ optiontype = (int*) realloc( optiontype ,
+ ((2 * max_options)+1)* sizeof(int) );
+ optionindex = (int*) realloc( optionindex,
+ ((2 * max_options)+1) * sizeof(int) );
+ if( options == NULL || optiontype == NULL || optionindex == NULL )
+ return false;
+ /* init new storage */
+ for( int i = max_options ; i < 2*max_options ; i++ ){
+ options[i] = NULL;
+ optiontype[i] = 0 ;
+ optionindex[i] = -1 ;
+ }
+ max_options = 2 * max_options ;
+ return true;
+}
+
+bool
+AnyOption::doubleCharStorage()
+{
+ optionchars = (char*) realloc( optionchars,
+ ((2*max_char_options)+1)*sizeof(char) );
+ optchartype = (int*) realloc( optchartype,
+ ((2*max_char_options)+1)*sizeof(int) );
+ optcharindex = (int*) realloc( optcharindex,
+ ((2*max_char_options)+1)*sizeof(int) );
+ if( optionchars == NULL ||
+ optchartype == NULL ||
+ optcharindex == NULL )
+ return false;
+ /* init new storage */
+ for( int i = max_char_options ; i < 2*max_char_options ; i++ ){
+ optionchars[i] = '0';
+ optchartype[i] = 0 ;
+ optcharindex[i] = -1 ;
+ }
+ max_char_options = 2 * max_char_options;
+ return true;
+}
+
+bool
+AnyOption::doubleUsageStorage()
+{
+ usage = (const char**)realloc( usage,
+ ((2*max_usage_lines)+1) * sizeof( const char*) );
+ if ( usage == NULL )
+ return false;
+ for( int i = max_usage_lines ; i < 2*max_usage_lines ; i++ )
+ usage[i] = NULL;
+ max_usage_lines = 2 * max_usage_lines ;
+ return true;
+
+}
+
+
+void
+AnyOption::cleanup()
+{
+ free (options);
+ free (optiontype);
+ free (optionindex);
+ free (optionchars);
+ free (optchartype);
+ free (optcharindex);
+ free (usage);
+ if( values != NULL )
+ free (values);
+ if( new_argv != NULL )
+ free (new_argv);
+}
+
+void
+AnyOption::setCommandPrefixChar( char _prefix )
+{
+ opt_prefix_char = _prefix;
+}
+
+void
+AnyOption::setCommandLongPrefix( char *_prefix )
+{
+ if( strlen( _prefix ) > MAX_LONG_PREFIX_LENGTH ){
+ *( _prefix + MAX_LONG_PREFIX_LENGTH ) = '\0';
+ }
+
+ strcpy (long_opt_prefix, _prefix);
+}
+
+void
+AnyOption::setFileCommentChar( char _comment )
+{
+ file_delimiter_char = _comment;
+}
+
+
+void
+AnyOption::setFileDelimiterChar( char _delimiter )
+{
+ file_comment_char = _delimiter ;
+}
+
+bool
+AnyOption::CommandSet()
+{
+ return( command_set );
+}
+
+bool
+AnyOption::FileSet()
+{
+ return( file_set );
+}
+
+void
+AnyOption::noPOSIX()
+{
+ posix_style = false;
+}
+
+bool
+AnyOption::POSIX()
+{
+ return posix_style;
+}
+
+
+void
+AnyOption::setVerbose()
+{
+ verbose = true ;
+}
+
+void
+AnyOption::printVerbose()
+{
+ if( verbose )
+ cout << endl ;
+}
+void
+AnyOption::printVerbose( const char *msg )
+{
+ if( verbose )
+ cout << msg ;
+}
+
+void
+AnyOption::printVerbose( char *msg )
+{
+ if( verbose )
+ cout << msg ;
+}
+
+void
+AnyOption::printVerbose( char ch )
+{
+ if( verbose )
+ cout << ch ;
+}
+
+bool
+AnyOption::hasOptions()
+{
+ return hasoptions;
+}
+
+void
+AnyOption::autoUsagePrint(bool _autousage)
+{
+ autousage = _autousage;
+}
+
+void
+AnyOption::useCommandArgs( int _argc, char **_argv )
+{
+ argc = _argc;
+ argv = _argv;
+ command_set = true;
+ appname = argv[0];
+ if(argc > 1) hasoptions = true;
+}
+
+void
+AnyOption::useFiileName( const char *_filename )
+{
+ filename = _filename;
+ file_set = true;
+}
+
+/*
+ * set methods for options
+ */
+
+void
+AnyOption::setCommandOption( const char *opt )
+{
+ addOption( opt , COMMAND_OPT );
+ g_value_counter++;
+}
+
+void
+AnyOption::setCommandOption( char opt )
+{
+ addOption( opt , COMMAND_OPT );
+ g_value_counter++;
+}
+
+void
+AnyOption::setCommandOption( const char *opt , char optchar )
+{
+ addOption( opt , COMMAND_OPT );
+ addOption( optchar , COMMAND_OPT );
+ g_value_counter++;
+}
+
+void
+AnyOption::setCommandFlag( const char *opt )
+{
+ addOption( opt , COMMAND_FLAG );
+ g_value_counter++;
+}
+
+void
+AnyOption::setCommandFlag( char opt )
+{
+ addOption( opt , COMMAND_FLAG );
+ g_value_counter++;
+}
+
+void
+AnyOption::setCommandFlag( const char *opt , char optchar )
+{
+ addOption( opt , COMMAND_FLAG );
+ addOption( optchar , COMMAND_FLAG );
+ g_value_counter++;
+}
+
+void
+AnyOption::setFileOption( const char *opt )
+{
+ addOption( opt , FILE_OPT );
+ g_value_counter++;
+}
+
+void
+AnyOption::setFileOption( char opt )
+{
+ addOption( opt , FILE_OPT );
+ g_value_counter++;
+}
+
+void
+AnyOption::setFileOption( const char *opt , char optchar )
+{
+ addOption( opt , FILE_OPT );
+ addOption( optchar, FILE_OPT );
+ g_value_counter++;
+}
+
+void
+AnyOption::setFileFlag( const char *opt )
+{
+ addOption( opt , FILE_FLAG );
+ g_value_counter++;
+}
+
+void
+AnyOption::setFileFlag( char opt )
+{
+ addOption( opt , FILE_FLAG );
+ g_value_counter++;
+}
+
+void
+AnyOption::setFileFlag( const char *opt , char optchar )
+{
+ addOption( opt , FILE_FLAG );
+ addOption( optchar , FILE_FLAG );
+ g_value_counter++;
+}
+
+void
+AnyOption::setOption( const char *opt )
+{
+ addOption( opt , COMMON_OPT );
+ g_value_counter++;
+}
+
+void
+AnyOption::setOption( char opt )
+{
+ addOption( opt , COMMON_OPT );
+ g_value_counter++;
+}
+
+void
+AnyOption::setOption( const char *opt , char optchar )
+{
+ addOption( opt , COMMON_OPT );
+ addOption( optchar , COMMON_OPT );
+ g_value_counter++;
+}
+
+void
+AnyOption::setFlag( const char *opt )
+{
+ addOption( opt , COMMON_FLAG );
+ g_value_counter++;
+}
+
+void
+AnyOption::setFlag( const char opt )
+{
+ addOption( opt , COMMON_FLAG );
+ g_value_counter++;
+}
+
+void
+AnyOption::setFlag( const char *opt , char optchar )
+{
+ addOption( opt , COMMON_FLAG );
+ addOption( optchar , COMMON_FLAG );
+ g_value_counter++;
+}
+
+void
+AnyOption::addOption( const char *opt, int type )
+{
+ if( option_counter >= max_options ){
+ if( doubleOptStorage() == false ){
+ addOptionError( opt );
+ return;
+ }
+ }
+ options[ option_counter ] = opt ;
+ optiontype[ option_counter ] = type ;
+ optionindex[ option_counter ] = g_value_counter;
+ option_counter++;
+}
+
+void
+AnyOption::addOption( char opt, int type )
+{
+ if( !POSIX() ){
+ printVerbose("Ignoring the option character \"");
+ printVerbose( opt );
+ printVerbose( "\" ( POSIX options are turned off )" );
+ printVerbose();
+ return;
+ }
+
+
+ if( optchar_counter >= max_char_options ){
+ if( doubleCharStorage() == false ){
+ addOptionError( opt );
+ return;
+ }
+ }
+ optionchars[ optchar_counter ] = opt ;
+ optchartype[ optchar_counter ] = type ;
+ optcharindex[ optchar_counter ] = g_value_counter;
+ optchar_counter++;
+}
+
+void
+AnyOption::addOptionError( const char *opt )
+{
+ cout << endl ;
+ cout << "OPTIONS ERROR : Failed allocating extra memory " << endl ;
+ cout << "While adding the option : \""<< opt << "\"" << endl;
+ cout << "Exiting." << endl ;
+ cout << endl ;
+ exit(0);
+}
+
+void
+AnyOption::addOptionError( char opt )
+{
+ cout << endl ;
+ cout << "OPTIONS ERROR : Failed allocating extra memory " << endl ;
+ cout << "While adding the option: \""<< opt << "\"" << endl;
+ cout << "Exiting." << endl ;
+ cout << endl ;
+ exit(0);
+}
+
+void
+AnyOption::processOptions()
+{
+ if( ! valueStoreOK() )
+ return;
+}
+
+void
+AnyOption::processCommandArgs(int max_args)
+{
+ max_legal_args = max_args;
+ processCommandArgs();
+}
+
+void
+AnyOption::processCommandArgs( int _argc, char **_argv, int max_args )
+{
+ max_legal_args = max_args;
+ processCommandArgs( _argc, _argv );
+}
+
+void
+AnyOption::processCommandArgs( int _argc, char **_argv )
+{
+ useCommandArgs( _argc, _argv );
+ processCommandArgs();
+}
+
+void
+AnyOption::processCommandArgs()
+{
+ if( ! ( valueStoreOK() && CommandSet() ) )
+ return;
+
+ if( max_legal_args == 0 )
+ max_legal_args = argc;
+ new_argv = (int*) malloc( (max_legal_args+1) * sizeof(int) );
+ for( int i = 1 ; i < argc ; i++ ){/* ignore first argv */
+ if( argv[i][0] == long_opt_prefix[0] &&
+ argv[i][1] == long_opt_prefix[1] ) { /* long GNU option */
+ int match_at = parseGNU( argv[i]+2 ); /* skip -- */
+ if( match_at >= 0 && i < argc-1 ) /* found match */
+ setValue( options[match_at] , argv[++i] );
+ }else if( argv[i][0] == opt_prefix_char ) { /* POSIX char */
+ if( POSIX() ){
+ char ch = parsePOSIX( argv[i]+1 );/* skip - */
+ if( ch != '0' && i < argc-1 ) /* matching char */
+ setValue( ch , argv[++i] );
+ } else { /* treat it as GNU option with a - */
+ int match_at = parseGNU( argv[i]+1 ); /* skip - */
+ if( match_at >= 0 && i < argc-1 ) /* found match */
+ setValue( options[match_at] , argv[++i] );
+ }
+ }else { /* not option but an argument keep index */
+ if( new_argc < max_legal_args ){
+ new_argv[ new_argc ] = i ;
+ new_argc++;
+ }else{ /* ignore extra arguments */
+ printVerbose( "Ignoring extra argument: " );
+ printVerbose( argv[i] );
+ printVerbose( );
+ printAutoUsage();
+ }
+ printVerbose( "Unknown command argument option : " );
+ printVerbose( argv[i] );
+ printVerbose( );
+ printAutoUsage();
+ }
+ }
+}
+
+char
+AnyOption::parsePOSIX( char* arg )
+{
+
+ for( unsigned int i = 0 ; i < strlen(arg) ; i++ ){
+ char ch = arg[i] ;
+ if( matchChar(ch) ) { /* keep matching flags till an option */
+ /*if last char argv[++i] is the value */
+ if( i == strlen(arg)-1 ){
+ return ch;
+ }else{/* else the rest of arg is the value */
+ i++; /* skip any '=' and ' ' */
+ while( arg[i] == whitespace
+ || arg[i] == equalsign )
+ i++;
+ setValue( ch , arg+i );
+ return '0';
+ }
+ }
+ }
+ printVerbose( "Unknown command argument option : " );
+ printVerbose( arg );
+ printVerbose( );
+ printAutoUsage();
+ return '0';
+}
+
+int
+AnyOption::parseGNU( char *arg )
+{
+ int split_at = 0;
+ /* if has a '=' sign get value */
+ for( unsigned int i = 0 ; i < strlen(arg) ; i++ ){
+ if(arg[i] == equalsign ){
+ split_at = i ; /* store index */
+ i = strlen(arg); /* get out of loop */
+ }
+ }
+ if( split_at > 0 ){ /* it is an option value pair */
+ char* tmp = (char*) malloc( (split_at+1)*sizeof(char) );
+ for( int i = 0 ; i < split_at ; i++ )
+ tmp[i] = arg[i];
+ tmp[split_at] = '\0';
+
+ if ( matchOpt( tmp ) >= 0 ){
+ setValue( options[matchOpt(tmp)] , arg+split_at+1 );
+ free (tmp);
+ }else{
+ printVerbose( "Unknown command argument option : " );
+ printVerbose( arg );
+ printVerbose( );
+ printAutoUsage();
+ free (tmp);
+ return -1;
+ }
+ }else{ /* regular options with no '=' sign */
+ return matchOpt(arg);
+ }
+ return -1;
+}
+
+
+int
+AnyOption::matchOpt( char *opt )
+{
+ for( int i = 0 ; i < option_counter ; i++ ){
+ if( strcmp( options[i], opt ) == 0 ){
+ if( optiontype[i] == COMMON_OPT ||
+ optiontype[i] == COMMAND_OPT )
+ { /* found option return index */
+ return i;
+ }else if( optiontype[i] == COMMON_FLAG ||
+ optiontype[i] == COMMAND_FLAG )
+ { /* found flag, set it */
+ setFlagOn( opt );
+ return -1;
+ }
+ }
+ }
+ printVerbose( "Unknown command argument option : " );
+ printVerbose( opt ) ;
+ printVerbose( );
+ printAutoUsage();
+ return -1;
+}
+bool
+AnyOption::matchChar( char c )
+{
+ for( int i = 0 ; i < optchar_counter ; i++ ){
+ if( optionchars[i] == c ) { /* found match */
+ if(optchartype[i] == COMMON_OPT ||
+ optchartype[i] == COMMAND_OPT )
+ { /* an option store and stop scanning */
+ return true;
+ }else if( optchartype[i] == COMMON_FLAG ||
+ optchartype[i] == COMMAND_FLAG ) { /* a flag store and keep scanning */
+ setFlagOn( c );
+ return false;
+ }
+ }
+ }
+ printVerbose( "Unknown command argument option : " );
+ printVerbose( c ) ;
+ printVerbose( );
+ printAutoUsage();
+ return false;
+}
+
+bool
+AnyOption::valueStoreOK( )
+{
+ int size= 0;
+ if( !set ){
+ if( g_value_counter > 0 ){
+ size = g_value_counter * sizeof(char*);
+ values = (char**)malloc( size );
+ for( int i = 0 ; i < g_value_counter ; i++)
+ values[i] = NULL;
+ set = true;
+ }
+ }
+ return set;
+}
+
+/*
+ * public get methods
+ */
+char*
+AnyOption::getValue( const char *option )
+{
+ if( !valueStoreOK() )
+ return NULL;
+
+ for( int i = 0 ; i < option_counter ; i++ ){
+ if( strcmp( options[i], option ) == 0 )
+ return values[ optionindex[i] ];
+ }
+ return NULL;
+}
+
+bool
+AnyOption::getFlag( const char *option )
+{
+ if( !valueStoreOK() )
+ return false;
+ for( int i = 0 ; i < option_counter ; i++ ){
+ if( strcmp( options[i], option ) == 0 )
+ return findFlag( values[ optionindex[i] ] );
+ }
+ return false;
+}
+
+char*
+AnyOption::getValue( char option )
+{
+ if( !valueStoreOK() )
+ return NULL;
+ for( int i = 0 ; i < optchar_counter ; i++ ){
+ if( optionchars[i] == option )
+ return values[ optcharindex[i] ];
+ }
+ return NULL;
+}
+
+bool
+AnyOption::getFlag( char option )
+{
+ if( !valueStoreOK() )
+ return false;
+ for( int i = 0 ; i < optchar_counter ; i++ ){
+ if( optionchars[i] == option )
+ return findFlag( values[ optcharindex[i] ] ) ;
+ }
+ return false;
+}
+
+bool
+AnyOption::findFlag( char* val )
+{
+ if( val == NULL )
+ return false;
+
+ if( strcmp( TRUE_FLAG , val ) == 0 )
+ return true;
+
+ return false;
+}
+
+/*
+ * private set methods
+ */
+bool
+AnyOption::setValue( const char *option , char *value )
+{
+ if( !valueStoreOK() )
+ return false;
+ for( int i = 0 ; i < option_counter ; i++ ){
+ if( strcmp( options[i], option ) == 0 ){
+ values[ optionindex[i] ] = (char*) malloc((strlen(value)+1)*sizeof(char));
+ strcpy( values[ optionindex[i] ], value );
+ return true;
+ }
+ }
+ return false;
+}
+
+bool
+AnyOption::setFlagOn( const char *option )
+{
+ if( !valueStoreOK() )
+ return false;
+ for( int i = 0 ; i < option_counter ; i++ ){
+ if( strcmp( options[i], option ) == 0 ){
+ values[ optionindex[i] ] = (char*) malloc((strlen(TRUE_FLAG)+1)*sizeof(char));
+ strcpy( values[ optionindex[i] ] , TRUE_FLAG );
+ return true;
+ }
+ }
+ return false;
+}
+
+bool
+AnyOption::setValue( char option , char *value )
+{
+ if( !valueStoreOK() )
+ return false;
+ for( int i = 0 ; i < optchar_counter ; i++ ){
+ if( optionchars[i] == option ){
+ values[ optcharindex[i] ] = (char*) malloc((strlen(value)+1)*sizeof(char));
+ strcpy( values[ optcharindex[i] ], value );
+ return true;
+ }
+ }
+ return false;
+}
+
+bool
+AnyOption::setFlagOn( char option )
+{
+ if( !valueStoreOK() )
+ return false;
+ for( int i = 0 ; i < optchar_counter ; i++ ){
+ if( optionchars[i] == option ){
+ values[ optcharindex[i] ] = (char*) malloc((strlen(TRUE_FLAG)+1)*sizeof(char));
+ strcpy( values[ optcharindex[i] ] , TRUE_FLAG );
+ return true;
+ }
+ }
+ return false;
+}
+
+
+int
+AnyOption::getArgc( )
+{
+ return new_argc;
+}
+
+char*
+AnyOption::getArgv( int index )
+{
+ if( index < new_argc ){
+ return ( argv[ new_argv[ index ] ] );
+ }
+ return NULL;
+}
+
+/* dotfile sub routines */
+
+bool
+AnyOption::processFile()
+{
+ if( ! (valueStoreOK() && FileSet()) )
+ return false;
+ return ( consumeFile(readFile()) );
+}
+
+bool
+AnyOption::processFile( const char *filename )
+{
+ useFiileName(filename );
+ return ( processFile() );
+}
+
+char*
+AnyOption::readFile()
+{
+ return ( readFile(filename) );
+}
+
+/*
+ * read the file contents to a character buffer
+ */
+
+char*
+AnyOption::readFile( const char* fname )
+{
+ int length;
+ char *buffer;
+ ifstream is;
+ is.open ( fname , ifstream::in );
+ if( ! is.good() ){
+ is.close();
+ return NULL;
+ }
+ is.seekg (0, ios::end);
+ length = is.tellg();
+ is.seekg (0, ios::beg);
+ buffer = (char*) malloc(length*sizeof(char));
+ is.read (buffer,length);
+ is.close();
+ return buffer;
+}
+
+/*
+ * scans a char* buffer for lines that does not
+ * start with the specified comment character.
+ */
+bool
+AnyOption::consumeFile( char *buffer )
+{
+
+ if( buffer == NULL )
+ return false;
+
+ char *cursor = buffer;/* preserve the ptr */
+ char *pline = NULL ;
+ int linelength = 0;
+ bool newline = true;
+ for( unsigned int i = 0 ; i < strlen( buffer ) ; i++ ){
+ if( *cursor == endofline ) { /* end of line */
+ if( pline != NULL ) /* valid line */
+ processLine( pline, linelength );
+ pline = NULL;
+ newline = true;
+ }else if( newline ){ /* start of line */
+ newline = false;
+ if( (*cursor != comment ) ){ /* not a comment */
+ pline = cursor ;
+ linelength = 0 ;
+ }
+ }
+ cursor++; /* keep moving */
+ linelength++;
+ }
+ free (buffer);
+ return true;
+}
+
+
+/*
+ * find a valid type value pair separated by a delimiter
+ * character and pass it to valuePairs()
+ * any line which is not valid will be considered a value
+ * and will get passed on to justValue()
+ *
+ * assuming delimiter is ':' the behaviour will be,
+ *
+ * width:10 - valid pair valuePairs( width, 10 );
+ * width : 10 - valid pair valuepairs( width, 10 );
+ *
+ * :::: - not valid
+ * width - not valid
+ * :10 - not valid
+ * width: - not valid
+ * :: - not valid
+ * : - not valid
+ *
+ */
+
+void
+AnyOption::processLine( char *theline, int length )
+{
+ bool found = false;
+ char *pline = (char*) malloc( (length+1)*sizeof(char) );
+ for( int i = 0 ; i < length ; i ++ )
+ pline[i]= *(theline++);
+ pline[length] = nullterminate;
+ char *cursor = pline ; /* preserve the ptr */
+ if( *cursor == delimiter || *(cursor+length-1) == delimiter ){
+ justValue( pline );/* line with start/end delimiter */
+ }else{
+ for( int i = 1 ; i < length-1 && !found ; i++){/* delimiter */
+ if( *cursor == delimiter ){
+ *(cursor-1) = nullterminate; /* two strings */
+ found = true;
+ valuePairs( pline , cursor+1 );
+ }
+ cursor++;
+ }
+ cursor++;
+ if( !found ) /* not a pair */
+ justValue( pline );
+ }
+ free (pline);
+}
+
+/*
+ * removes trailing and preceeding whitespaces from a string
+ */
+char*
+AnyOption::chomp( char *str )
+{
+ while( *str == whitespace )
+ str++;
+ char *end = str+strlen(str)-1;
+ while( *end == whitespace )
+ end--;
+ *(end+1) = nullterminate;
+ return str;
+}
+
+void
+AnyOption::valuePairs( char *type, char *value )
+{
+ if ( strlen(chomp(type)) == 1 ){ /* this is a char option */
+ for( int i = 0 ; i < optchar_counter ; i++ ){
+ if( optionchars[i] == type[0] ){ /* match */
+ if( optchartype[i] == COMMON_OPT ||
+ optchartype[i] == FILE_OPT )
+ {
+ setValue( type[0] , chomp(value) );
+ return;
+ }
+ }
+ }
+ }
+ /* if no char options matched */
+ for( int i = 0 ; i < option_counter ; i++ ){
+ if( strcmp( options[i], type ) == 0 ){ /* match */
+ if( optiontype[i] == COMMON_OPT ||
+ optiontype[i] == FILE_OPT )
+ {
+ setValue( type , chomp(value) );
+ return;
+ }
+ }
+ }
+ printVerbose( "Unknown option in resourcefile : " );
+ printVerbose( type );
+ printVerbose( );
+}
+
+void
+AnyOption::justValue( char *type )
+{
+
+ if ( strlen(chomp(type)) == 1 ){ /* this is a char option */
+ for( int i = 0 ; i < optchar_counter ; i++ ){
+ if( optionchars[i] == type[0] ){ /* match */
+ if( optchartype[i] == COMMON_FLAG ||
+ optchartype[i] == FILE_FLAG )
+ {
+ setFlagOn( type[0] );
+ return;
+ }
+ }
+ }
+ }
+ /* if no char options matched */
+ for( int i = 0 ; i < option_counter ; i++ ){
+ if( strcmp( options[i], type ) == 0 ){ /* match */
+ if( optiontype[i] == COMMON_FLAG ||
+ optiontype[i] == FILE_FLAG )
+ {
+ setFlagOn( type );
+ return;
+ }
+ }
+ }
+ printVerbose( "Unknown option in resourcefile : " );
+ printVerbose( type );
+ printVerbose( );
+}
+
+/*
+ * usage and help
+ */
+
+
+void
+AnyOption::printAutoUsage()
+{
+ if( autousage ) printUsage();
+}
+
+void
+AnyOption::printUsage()
+{
+
+ if( once ) {
+ once = false ;
+ cout << endl ;
+ for( int i = 0 ; i < usage_lines ; i++ )
+ cout << usage[i] << endl ;
+ cout << endl ;
+ }
+}
+
+
+void
+AnyOption::addUsage( const char *line )
+{
+ if( usage_lines >= max_usage_lines ){
+ if( doubleUsageStorage() == false ){
+ addUsageError( line );
+ exit(1);
+ }
+ }
+ usage[ usage_lines ] = line ;
+ usage_lines++;
+}
+
+void
+AnyOption::addUsageError( const char *line )
+{
+ cout << endl ;
+ cout << "OPTIONS ERROR : Failed allocating extra memory " << endl ;
+ cout << "While adding the usage/help : \""<< line << "\"" << endl;
+ cout << "Exiting." << endl ;
+ cout << endl ;
+ exit(0);
+
+}
diff --git a/mmc_updater/depends/AnyOption/anyoption.h b/mmc_updater/depends/AnyOption/anyoption.h
new file mode 100644
index 00000000..01501df2
--- /dev/null
+++ b/mmc_updater/depends/AnyOption/anyoption.h
@@ -0,0 +1,270 @@
+#ifndef _ANYOPTION_H
+#define _ANYOPTION_H
+
+#include <iostream>
+#include <fstream>
+#include <stdlib.h>
+#include <string>
+
+#define COMMON_OPT 1
+#define COMMAND_OPT 2
+#define FILE_OPT 3
+#define COMMON_FLAG 4
+#define COMMAND_FLAG 5
+#define FILE_FLAG 6
+
+#define COMMAND_OPTION_TYPE 1
+#define COMMAND_FLAG_TYPE 2
+#define FILE_OPTION_TYPE 3
+#define FILE_FLAG_TYPE 4
+#define UNKNOWN_TYPE 5
+
+#define DEFAULT_MAXOPTS 10
+#define MAX_LONG_PREFIX_LENGTH 2
+
+#define DEFAULT_MAXUSAGE 3
+#define DEFAULT_MAXHELP 10
+
+#define TRUE_FLAG "true"
+
+using namespace std;
+
+class AnyOption
+{
+
+public: /* the public interface */
+ AnyOption();
+ AnyOption(int maxoptions );
+ AnyOption(int maxoptions , int maxcharoptions);
+ ~AnyOption();
+
+ /*
+ * following set methods specifies the
+ * special characters and delimiters
+ * if not set traditional defaults will be used
+ */
+
+ void setCommandPrefixChar( char _prefix ); /* '-' in "-w" */
+ void setCommandLongPrefix( char *_prefix ); /* '--' in "--width" */
+ void setFileCommentChar( char _comment ); /* '#' in shellscripts */
+ void setFileDelimiterChar( char _delimiter );/* ':' in "width : 100" */
+
+ /*
+ * provide the input for the options
+ * like argv[] for commndline and the
+ * option file name to use;
+ */
+
+ void useCommandArgs( int _argc, char **_argv );
+ void useFiileName( const char *_filename );
+
+ /*
+ * turn off the POSIX style options
+ * this means anything starting with a '-' or "--"
+ * will be considered a valid option
+ * which alo means you cannot add a bunch of
+ * POIX options chars together like "-lr" for "-l -r"
+ *
+ */
+
+ void noPOSIX();
+
+ /*
+ * prints warning verbose if you set anything wrong
+ */
+ void setVerbose();
+
+
+ /*
+ * there are two types of options
+ *
+ * Option - has an associated value ( -w 100 )
+ * Flag - no value, just a boolean flag ( -nogui )
+ *
+ * the options can be either a string ( GNU style )
+ * or a character ( traditional POSIX style )
+ * or both ( --width, -w )
+ *
+ * the options can be common to the commandline and
+ * the optionfile, or can belong only to either of
+ * commandline and optionfile
+ *
+ * following set methods, handle all the aboove
+ * cases of options.
+ */
+
+ /* options comman to command line and option file */
+ void setOption( const char *opt_string );
+ void setOption( char opt_char );
+ void setOption( const char *opt_string , char opt_char );
+ void setFlag( const char *opt_string );
+ void setFlag( char opt_char );
+ void setFlag( const char *opt_string , char opt_char );
+
+ /* options read from commandline only */
+ void setCommandOption( const char *opt_string );
+ void setCommandOption( char opt_char );
+ void setCommandOption( const char *opt_string , char opt_char );
+ void setCommandFlag( const char *opt_string );
+ void setCommandFlag( char opt_char );
+ void setCommandFlag( const char *opt_string , char opt_char );
+
+ /* options read from an option file only */
+ void setFileOption( const char *opt_string );
+ void setFileOption( char opt_char );
+ void setFileOption( const char *opt_string , char opt_char );
+ void setFileFlag( const char *opt_string );
+ void setFileFlag( char opt_char );
+ void setFileFlag( const char *opt_string , char opt_char );
+
+ /*
+ * process the options, registerd using
+ * useCommandArgs() and useFileName();
+ */
+ void processOptions();
+ void processCommandArgs();
+ void processCommandArgs( int max_args );
+ bool processFile();
+
+ /*
+ * process the specified options
+ */
+ void processCommandArgs( int _argc, char **_argv );
+ void processCommandArgs( int _argc, char **_argv, int max_args );
+ bool processFile( const char *_filename );
+
+ /*
+ * get the value of the options
+ * will return NULL if no value is set
+ */
+ char *getValue( const char *_option );
+ bool getFlag( const char *_option );
+ char *getValue( char _optchar );
+ bool getFlag( char _optchar );
+
+ /*
+ * Print Usage
+ */
+ void printUsage();
+ void printAutoUsage();
+ void addUsage( const char *line );
+ void printHelp();
+ /* print auto usage printing for unknown options or flag */
+ void autoUsagePrint(bool flag);
+
+ /*
+ * get the argument count and arguments sans the options
+ */
+ int getArgc();
+ char* getArgv( int index );
+ bool hasOptions();
+
+private: /* the hidden data structure */
+ int argc; /* commandline arg count */
+ char **argv; /* commndline args */
+ const char* filename; /* the option file */
+ char* appname; /* the application name from argv[0] */
+
+ int *new_argv; /* arguments sans options (index to argv) */
+ int new_argc; /* argument count sans the options */
+ int max_legal_args; /* ignore extra arguments */
+
+
+ /* option strings storage + indexing */
+ int max_options; /* maximum number of options */
+ const char **options; /* storage */
+ int *optiontype; /* type - common, command, file */
+ int *optionindex; /* index into value storage */
+ int option_counter; /* counter for added options */
+
+ /* option chars storage + indexing */
+ int max_char_options; /* maximum number options */
+ char *optionchars; /* storage */
+ int *optchartype; /* type - common, command, file */
+ int *optcharindex; /* index into value storage */
+ int optchar_counter; /* counter for added options */
+
+ /* values */
+ char **values; /* common value storage */
+ int g_value_counter; /* globally updated value index LAME! */
+
+ /* help and usage */
+ const char **usage; /* usage */
+ int max_usage_lines; /* max usage lines reseverd */
+ int usage_lines; /* number of usage lines */
+
+ bool command_set; /* if argc/argv were provided */
+ bool file_set; /* if a filename was provided */
+ bool mem_allocated; /* if memory allocated in init() */
+ bool posix_style; /* enables to turn off POSIX style options */
+ bool verbose; /* silent|verbose */
+ bool print_usage; /* usage verbose */
+ bool print_help; /* help verbose */
+
+ char opt_prefix_char; /* '-' in "-w" */
+ char long_opt_prefix[MAX_LONG_PREFIX_LENGTH + 1]; /* '--' in "--width" */
+ char file_delimiter_char; /* ':' in width : 100 */
+ char file_comment_char; /* '#' in "#this is a comment" */
+ char equalsign;
+ char comment;
+ char delimiter;
+ char endofline;
+ char whitespace;
+ char nullterminate;
+
+ bool set; //was static member
+ bool once; //was static member
+
+ bool hasoptions;
+ bool autousage;
+
+private: /* the hidden utils */
+ void init();
+ void init(int maxopt, int maxcharopt );
+ bool alloc();
+ void cleanup();
+ bool valueStoreOK();
+
+ /* grow storage arrays as required */
+ bool doubleOptStorage();
+ bool doubleCharStorage();
+ bool doubleUsageStorage();
+
+ bool setValue( const char *option , char *value );
+ bool setFlagOn( const char *option );
+ bool setValue( char optchar , char *value);
+ bool setFlagOn( char optchar );
+
+ void addOption( const char* option , int type );
+ void addOption( char optchar , int type );
+ void addOptionError( const char *opt);
+ void addOptionError( char opt);
+ bool findFlag( char* value );
+ void addUsageError( const char *line );
+ bool CommandSet();
+ bool FileSet();
+ bool POSIX();
+
+ char parsePOSIX( char* arg );
+ int parseGNU( char *arg );
+ bool matchChar( char c );
+ int matchOpt( char *opt );
+
+ /* dot file methods */
+ char *readFile();
+ char *readFile( const char* fname );
+ bool consumeFile( char *buffer );
+ void processLine( char *theline, int length );
+ char *chomp( char *str );
+ void valuePairs( char *type, char *value );
+ void justValue( char *value );
+
+ void printVerbose( const char *msg );
+ void printVerbose( char *msg );
+ void printVerbose( char ch );
+ void printVerbose( );
+
+
+};
+
+#endif /* ! _ANYOPTION_H */
diff --git a/mmc_updater/depends/tinyxml/CMakeLists.txt b/mmc_updater/depends/tinyxml/CMakeLists.txt
new file mode 100644
index 00000000..25c9bb92
--- /dev/null
+++ b/mmc_updater/depends/tinyxml/CMakeLists.txt
@@ -0,0 +1,24 @@
+# TinyXML 1.0.1
+project(tinyxml)
+
+cmake_minimum_required(VERSION 2.6)
+
+Add_definitions(-DTIXML_USE_STL)
+
+set(SOURCES
+ tinystr.cpp
+ tinyxml.cpp
+ tinyxmlerror.cpp
+ tinyxmlparser.cpp
+)
+
+set(HEADERS
+ tinystr.h
+ tinyxml.h
+)
+
+add_library(tinyxml
+ ${SOURCES}
+ ${HEADERS}
+)
+
diff --git a/mmc_updater/depends/tinyxml/readme.txt b/mmc_updater/depends/tinyxml/readme.txt
new file mode 100644
index 00000000..89d9e8d3
--- /dev/null
+++ b/mmc_updater/depends/tinyxml/readme.txt
@@ -0,0 +1,530 @@
+/** @mainpage
+
+<h1> TinyXML </h1>
+
+TinyXML is a simple, small, C++ XML parser that can be easily
+integrated into other programs.
+
+<h2> What it does. </h2>
+
+In brief, TinyXML parses an XML document, and builds from that a
+Document Object Model (DOM) that can be read, modified, and saved.
+
+XML stands for "eXtensible Markup Language." It allows you to create
+your own document markups. Where HTML does a very good job of marking
+documents for browsers, XML allows you to define any kind of document
+markup, for example a document that describes a "to do" list for an
+organizer application. XML is a very structured and convenient format.
+All those random file formats created to store application data can
+all be replaced with XML. One parser for everything.
+
+The best place for the complete, correct, and quite frankly hard to
+read spec is at <a href="http://www.w3.org/TR/2004/REC-xml-20040204/">
+http://www.w3.org/TR/2004/REC-xml-20040204/</a>. An intro to XML
+(that I really like) can be found at
+<a href="http://skew.org/xml/tutorial/">http://skew.org/xml/tutorial</a>.
+
+There are different ways to access and interact with XML data.
+TinyXML uses a Document Object Model (DOM), meaning the XML data is parsed
+into a C++ objects that can be browsed and manipulated, and then
+written to disk or another output stream. You can also construct an XML document
+from scratch with C++ objects and write this to disk or another output
+stream.
+
+TinyXML is designed to be easy and fast to learn. It is two headers
+and four cpp files. Simply add these to your project and off you go.
+There is an example file - xmltest.cpp - to get you started.
+
+TinyXML is released under the ZLib license,
+so you can use it in open source or commercial code. The details
+of the license are at the top of every source file.
+
+TinyXML attempts to be a flexible parser, but with truly correct and
+compliant XML output. TinyXML should compile on any reasonably C++
+compliant system. It does not rely on exceptions or RTTI. It can be
+compiled with or without STL support. TinyXML fully supports
+the UTF-8 encoding, and the first 64k character entities.
+
+
+<h2> What it doesn't do. </h2>
+
+TinyXML doesn't parse or use DTDs (Document Type Definitions) or XSLs
+(eXtensible Stylesheet Language.) There are other parsers out there
+(check out www.sourceforge.org, search for XML) that are much more fully
+featured. But they are also much bigger, take longer to set up in
+your project, have a higher learning curve, and often have a more
+restrictive license. If you are working with browsers or have more
+complete XML needs, TinyXML is not the parser for you.
+
+The following DTD syntax will not parse at this time in TinyXML:
+
+@verbatim
+ <!DOCTYPE Archiv [
+ <!ELEMENT Comment (#PCDATA)>
+ ]>
+@endverbatim
+
+because TinyXML sees this as a !DOCTYPE node with an illegally
+embedded !ELEMENT node. This may be addressed in the future.
+
+<h2> Tutorials. </h2>
+
+For the impatient, here is a tutorial to get you going. A great way to get started,
+but it is worth your time to read this (very short) manual completely.
+
+- @subpage tutorial0
+
+<h2> Code Status. </h2>
+
+TinyXML is mature, tested code. It is very stable. If you find
+bugs, please file a bug report on the sourceforge web site
+(www.sourceforge.net/projects/tinyxml). We'll get them straightened
+out as soon as possible.
+
+There are some areas of improvement; please check sourceforge if you are
+interested in working on TinyXML.
+
+<h2> Related Projects </h2>
+
+TinyXML projects you may find useful! (Descriptions provided by the projects.)
+
+<ul>
+<li> <b>TinyXPath</b> (http://tinyxpath.sourceforge.net). TinyXPath is a small footprint
+ XPath syntax decoder, written in C++.</li>
+<li> <b>TinyXML++</b> (http://code.google.com/p/ticpp/). TinyXML++ is a completely new
+ interface to TinyXML that uses MANY of the C++ strengths. Templates,
+ exceptions, and much better error handling.</li>
+</ul>
+
+<h2> Features </h2>
+
+<h3> Using STL </h3>
+
+TinyXML can be compiled to use or not use STL. When using STL, TinyXML
+uses the std::string class, and fully supports std::istream, std::ostream,
+operator<<, and operator>>. Many API methods have both 'const char*' and
+'const std::string&' forms.
+
+When STL support is compiled out, no STL files are included whatsoever. All
+the string classes are implemented by TinyXML itself. API methods
+all use the 'const char*' form for input.
+
+Use the compile time #define:
+
+ TIXML_USE_STL
+
+to compile one version or the other. This can be passed by the compiler,
+or set as the first line of "tinyxml.h".
+
+Note: If compiling the test code in Linux, setting the environment
+variable TINYXML_USE_STL=YES/NO will control STL compilation. In the
+Windows project file, STL and non STL targets are provided. In your project,
+It's probably easiest to add the line "#define TIXML_USE_STL" as the first
+line of tinyxml.h.
+
+<h3> UTF-8 </h3>
+
+TinyXML supports UTF-8 allowing to manipulate XML files in any language. TinyXML
+also supports "legacy mode" - the encoding used before UTF-8 support and
+probably best described as "extended ascii".
+
+Normally, TinyXML will try to detect the correct encoding and use it. However,
+by setting the value of TIXML_DEFAULT_ENCODING in the header file, TinyXML
+can be forced to always use one encoding.
+
+TinyXML will assume Legacy Mode until one of the following occurs:
+<ol>
+ <li> If the non-standard but common "UTF-8 lead bytes" (0xef 0xbb 0xbf)
+ begin the file or data stream, TinyXML will read it as UTF-8. </li>
+ <li> If the declaration tag is read, and it has an encoding="UTF-8", then
+ TinyXML will read it as UTF-8. </li>
+ <li> If the declaration tag is read, and it has no encoding specified, then TinyXML will
+ read it as UTF-8. </li>
+ <li> If the declaration tag is read, and it has an encoding="something else", then TinyXML
+ will read it as Legacy Mode. In legacy mode, TinyXML will work as it did before. It's
+ not clear what that mode does exactly, but old content should keep working.</li>
+ <li> Until one of the above criteria is met, TinyXML runs in Legacy Mode.</li>
+</ol>
+
+What happens if the encoding is incorrectly set or detected? TinyXML will try
+to read and pass through text seen as improperly encoded. You may get some strange results or
+mangled characters. You may want to force TinyXML to the correct mode.
+
+You may force TinyXML to Legacy Mode by using LoadFile( TIXML_ENCODING_LEGACY ) or
+LoadFile( filename, TIXML_ENCODING_LEGACY ). You may force it to use legacy mode all
+the time by setting TIXML_DEFAULT_ENCODING = TIXML_ENCODING_LEGACY. Likewise, you may
+force it to TIXML_ENCODING_UTF8 with the same technique.
+
+For English users, using English XML, UTF-8 is the same as low-ASCII. You
+don't need to be aware of UTF-8 or change your code in any way. You can think
+of UTF-8 as a "superset" of ASCII.
+
+UTF-8 is not a double byte format - but it is a standard encoding of Unicode!
+TinyXML does not use or directly support wchar, TCHAR, or Microsoft's _UNICODE at this time.
+It is common to see the term "Unicode" improperly refer to UTF-16, a wide byte encoding
+of unicode. This is a source of confusion.
+
+For "high-ascii" languages - everything not English, pretty much - TinyXML can
+handle all languages, at the same time, as long as the XML is encoded
+in UTF-8. That can be a little tricky, older programs and operating systems
+tend to use the "default" or "traditional" code page. Many apps (and almost all
+modern ones) can output UTF-8, but older or stubborn (or just broken) ones
+still output text in the default code page.
+
+For example, Japanese systems traditionally use SHIFT-JIS encoding.
+Text encoded as SHIFT-JIS can not be read by TinyXML.
+A good text editor can import SHIFT-JIS and then save as UTF-8.
+
+The <a href="http://skew.org/xml/tutorial/">Skew.org link</a> does a great
+job covering the encoding issue.
+
+The test file "utf8test.xml" is an XML containing English, Spanish, Russian,
+and Simplified Chinese. (Hopefully they are translated correctly). The file
+"utf8test.gif" is a screen capture of the XML file, rendered in IE. Note that
+if you don't have the correct fonts (Simplified Chinese or Russian) on your
+system, you won't see output that matches the GIF file even if you can parse
+it correctly. Also note that (at least on my Windows machine) console output
+is in a Western code page, so that Print() or printf() cannot correctly display
+the file. This is not a bug in TinyXML - just an OS issue. No data is lost or
+destroyed by TinyXML. The console just doesn't render UTF-8.
+
+
+<h3> Entities </h3>
+TinyXML recognizes the pre-defined "character entities", meaning special
+characters. Namely:
+
+@verbatim
+ &amp; &
+ &lt; <
+ &gt; >
+ &quot; "
+ &apos; '
+@endverbatim
+
+These are recognized when the XML document is read, and translated to there
+UTF-8 equivalents. For instance, text with the XML of:
+
+@verbatim
+ Far &amp; Away
+@endverbatim
+
+will have the Value() of "Far & Away" when queried from the TiXmlText object,
+and will be written back to the XML stream/file as an ampersand. Older versions
+of TinyXML "preserved" character entities, but the newer versions will translate
+them into characters.
+
+Additionally, any character can be specified by its Unicode code point:
+The syntax "&#xA0;" or "&#160;" are both to the non-breaking space characher.
+
+<h3> Printing </h3>
+TinyXML can print output in several different ways that all have strengths and limitations.
+
+- Print( FILE* ). Output to a std-C stream, which includes all C files as well as stdout.
+ - "Pretty prints", but you don't have control over printing options.
+ - The output is streamed directly to the FILE object, so there is no memory overhead
+ in the TinyXML code.
+ - used by Print() and SaveFile()
+
+- operator<<. Output to a c++ stream.
+ - Integrates with standart C++ iostreams.
+ - Outputs in "network printing" mode without line breaks. Good for network transmission
+ and moving XML between C++ objects, but hard for a human to read.
+
+- TiXmlPrinter. Output to a std::string or memory buffer.
+ - API is less concise
+ - Future printing options will be put here.
+ - Printing may change slightly in future versions as it is refined and expanded.
+
+<h3> Streams </h3>
+With TIXML_USE_STL on TinyXML supports C++ streams (operator <<,>>) streams as well
+as C (FILE*) streams. There are some differences that you may need to be aware of.
+
+C style output:
+ - based on FILE*
+ - the Print() and SaveFile() methods
+
+ Generates formatted output, with plenty of white space, intended to be as
+ human-readable as possible. They are very fast, and tolerant of ill formed
+ XML documents. For example, an XML document that contains 2 root elements
+ and 2 declarations, will still print.
+
+C style input:
+ - based on FILE*
+ - the Parse() and LoadFile() methods
+
+ A fast, tolerant read. Use whenever you don't need the C++ streams.
+
+C++ style output:
+ - based on std::ostream
+ - operator<<
+
+ Generates condensed output, intended for network transmission rather than
+ readability. Depending on your system's implementation of the ostream class,
+ these may be somewhat slower. (Or may not.) Not tolerant of ill formed XML:
+ a document should contain the correct one root element. Additional root level
+ elements will not be streamed out.
+
+C++ style input:
+ - based on std::istream
+ - operator>>
+
+ Reads XML from a stream, making it useful for network transmission. The tricky
+ part is knowing when the XML document is complete, since there will almost
+ certainly be other data in the stream. TinyXML will assume the XML data is
+ complete after it reads the root element. Put another way, documents that
+ are ill-constructed with more than one root element will not read correctly.
+ Also note that operator>> is somewhat slower than Parse, due to both
+ implementation of the STL and limitations of TinyXML.
+
+<h3> White space </h3>
+The world simply does not agree on whether white space should be kept, or condensed.
+For example, pretend the '_' is a space, and look at "Hello____world". HTML, and
+at least some XML parsers, will interpret this as "Hello_world". They condense white
+space. Some XML parsers do not, and will leave it as "Hello____world". (Remember
+to keep pretending the _ is a space.) Others suggest that __Hello___world__ should become
+Hello___world.
+
+It's an issue that hasn't been resolved to my satisfaction. TinyXML supports the
+first 2 approaches. Call TiXmlBase::SetCondenseWhiteSpace( bool ) to set the desired behavior.
+The default is to condense white space.
+
+If you change the default, you should call TiXmlBase::SetCondenseWhiteSpace( bool )
+before making any calls to Parse XML data, and I don't recommend changing it after
+it has been set.
+
+
+<h3> Handles </h3>
+
+Where browsing an XML document in a robust way, it is important to check
+for null returns from method calls. An error safe implementation can
+generate a lot of code like:
+
+@verbatim
+TiXmlElement* root = document.FirstChildElement( "Document" );
+if ( root )
+{
+ TiXmlElement* element = root->FirstChildElement( "Element" );
+ if ( element )
+ {
+ TiXmlElement* child = element->FirstChildElement( "Child" );
+ if ( child )
+ {
+ TiXmlElement* child2 = child->NextSiblingElement( "Child" );
+ if ( child2 )
+ {
+ // Finally do something useful.
+@endverbatim
+
+Handles have been introduced to clean this up. Using the TiXmlHandle class,
+the previous code reduces to:
+
+@verbatim
+TiXmlHandle docHandle( &document );
+TiXmlElement* child2 = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).Child( "Child", 1 ).ToElement();
+if ( child2 )
+{
+ // do something useful
+@endverbatim
+
+Which is much easier to deal with. See TiXmlHandle for more information.
+
+
+<h3> Row and Column tracking </h3>
+Being able to track nodes and attributes back to their origin location
+in source files can be very important for some applications. Additionally,
+knowing where parsing errors occured in the original source can be very
+time saving.
+
+TinyXML can tracks the row and column origin of all nodes and attributes
+in a text file. The TiXmlBase::Row() and TiXmlBase::Column() methods return
+the origin of the node in the source text. The correct tabs can be
+configured in TiXmlDocument::SetTabSize().
+
+
+<h2> Using and Installing </h2>
+
+To Compile and Run xmltest:
+
+A Linux Makefile and a Windows Visual C++ .dsw file is provided.
+Simply compile and run. It will write the file demotest.xml to your
+disk and generate output on the screen. It also tests walking the
+DOM by printing out the number of nodes found using different
+techniques.
+
+The Linux makefile is very generic and runs on many systems - it
+is currently tested on mingw and
+MacOSX. You do not need to run 'make depend'. The dependecies have been
+hard coded.
+
+<h3>Windows project file for VC6</h3>
+<ul>
+<li>tinyxml: tinyxml library, non-STL </li>
+<li>tinyxmlSTL: tinyxml library, STL </li>
+<li>tinyXmlTest: test app, non-STL </li>
+<li>tinyXmlTestSTL: test app, STL </li>
+</ul>
+
+<h3>Makefile</h3>
+At the top of the makefile you can set:
+
+PROFILE, DEBUG, and TINYXML_USE_STL. Details (such that they are) are in
+the makefile.
+
+In the tinyxml directory, type "make clean" then "make". The executable
+file 'xmltest' will be created.
+
+
+
+<h3>To Use in an Application:</h3>
+
+Add tinyxml.cpp, tinyxml.h, tinyxmlerror.cpp, tinyxmlparser.cpp, tinystr.cpp, and tinystr.h to your
+project or make file. That's it! It should compile on any reasonably
+compliant C++ system. You do not need to enable exceptions or
+RTTI for TinyXML.
+
+
+<h2> How TinyXML works. </h2>
+
+An example is probably the best way to go. Take:
+@verbatim
+ <?xml version="1.0" standalone=no>
+ <!-- Our to do list data -->
+ <ToDo>
+ <Item priority="1"> Go to the <bold>Toy store!</bold></Item>
+ <Item priority="2"> Do bills</Item>
+ </ToDo>
+@endverbatim
+
+Its not much of a To Do list, but it will do. To read this file
+(say "demo.xml") you would create a document, and parse it in:
+@verbatim
+ TiXmlDocument doc( "demo.xml" );
+ doc.LoadFile();
+@endverbatim
+
+And its ready to go. Now lets look at some lines and how they
+relate to the DOM.
+
+@verbatim
+<?xml version="1.0" standalone=no>
+@endverbatim
+
+ The first line is a declaration, and gets turned into the
+ TiXmlDeclaration class. It will be the first child of the
+ document node.
+
+ This is the only directive/special tag parsed by TinyXML.
+ Generally directive tags are stored in TiXmlUnknown so the
+ commands wont be lost when it is saved back to disk.
+
+@verbatim
+<!-- Our to do list data -->
+@endverbatim
+
+ A comment. Will become a TiXmlComment object.
+
+@verbatim
+<ToDo>
+@endverbatim
+
+ The "ToDo" tag defines a TiXmlElement object. This one does not have
+ any attributes, but does contain 2 other elements.
+
+@verbatim
+<Item priority="1">
+@endverbatim
+
+ Creates another TiXmlElement which is a child of the "ToDo" element.
+ This element has 1 attribute, with the name "priority" and the value
+ "1".
+
+@verbatim
+Go to the
+@endverbatim
+
+ A TiXmlText. This is a leaf node and cannot contain other nodes.
+ It is a child of the "Item" TiXmlElement.
+
+@verbatim
+<bold>
+@endverbatim
+
+
+ Another TiXmlElement, this one a child of the "Item" element.
+
+Etc.
+
+Looking at the entire object tree, you end up with:
+@verbatim
+TiXmlDocument "demo.xml"
+ TiXmlDeclaration "version='1.0'" "standalone=no"
+ TiXmlComment " Our to do list data"
+ TiXmlElement "ToDo"
+ TiXmlElement "Item" Attribtutes: priority = 1
+ TiXmlText "Go to the "
+ TiXmlElement "bold"
+ TiXmlText "Toy store!"
+ TiXmlElement "Item" Attributes: priority=2
+ TiXmlText "Do bills"
+@endverbatim
+
+<h2> Documentation </h2>
+
+The documentation is build with Doxygen, using the 'dox'
+configuration file.
+
+<h2> License </h2>
+
+TinyXML is released under the zlib license:
+
+This software is provided 'as-is', without any express or implied
+warranty. In no event will the authors be held liable for any
+damages arising from the use of this software.
+
+Permission is granted to anyone to use this software for any
+purpose, including commercial applications, and to alter it and
+redistribute it freely, subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must
+not claim that you wrote the original software. If you use this
+software in a product, an acknowledgment in the product documentation
+would be appreciated but is not required.
+
+2. Altered source versions must be plainly marked as such, and
+must not be misrepresented as being the original software.
+
+3. This notice may not be removed or altered from any source
+distribution.
+
+<h2> References </h2>
+
+The World Wide Web Consortium is the definitive standard body for
+XML, and their web pages contain huge amounts of information.
+
+The definitive spec: <a href="http://www.w3.org/TR/2004/REC-xml-20040204/">
+http://www.w3.org/TR/2004/REC-xml-20040204/</a>
+
+I also recommend "XML Pocket Reference" by Robert Eckstein and published by
+OReilly...the book that got the whole thing started.
+
+<h2> Contributors, Contacts, and a Brief History </h2>
+
+Thanks very much to everyone who sends suggestions, bugs, ideas, and
+encouragement. It all helps, and makes this project fun. A special thanks
+to the contributors on the web pages that keep it lively.
+
+So many people have sent in bugs and ideas, that rather than list here
+we try to give credit due in the "changes.txt" file.
+
+TinyXML was originally written by Lee Thomason. (Often the "I" still
+in the documentation.) Lee reviews changes and releases new versions,
+with the help of Yves Berquin, Andrew Ellerton, and the tinyXml community.
+
+We appreciate your suggestions, and would love to know if you
+use TinyXML. Hopefully you will enjoy it and find it useful.
+Please post questions, comments, file bugs, or contact us at:
+
+www.sourceforge.net/projects/tinyxml
+
+Lee Thomason, Yves Berquin, Andrew Ellerton
+*/
diff --git a/mmc_updater/depends/tinyxml/tinystr.cpp b/mmc_updater/depends/tinyxml/tinystr.cpp
new file mode 100644
index 00000000..06657682
--- /dev/null
+++ b/mmc_updater/depends/tinyxml/tinystr.cpp
@@ -0,0 +1,111 @@
+/*
+www.sourceforge.net/projects/tinyxml
+
+This software is provided 'as-is', without any express or implied
+warranty. In no event will the authors be held liable for any
+damages arising from the use of this software.
+
+Permission is granted to anyone to use this software for any
+purpose, including commercial applications, and to alter it and
+redistribute it freely, subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must
+not claim that you wrote the original software. If you use this
+software in a product, an acknowledgment in the product documentation
+would be appreciated but is not required.
+
+2. Altered source versions must be plainly marked as such, and
+must not be misrepresented as being the original software.
+
+3. This notice may not be removed or altered from any source
+distribution.
+*/
+
+
+#ifndef TIXML_USE_STL
+
+#include "tinystr.h"
+
+// Error value for find primitive
+const TiXmlString::size_type TiXmlString::npos = static_cast< TiXmlString::size_type >(-1);
+
+
+// Null rep.
+TiXmlString::Rep TiXmlString::nullrep_ = { 0, 0, { '\0' } };
+
+
+void TiXmlString::reserve (size_type cap)
+{
+ if (cap > capacity())
+ {
+ TiXmlString tmp;
+ tmp.init(length(), cap);
+ memcpy(tmp.start(), data(), length());
+ swap(tmp);
+ }
+}
+
+
+TiXmlString& TiXmlString::assign(const char* str, size_type len)
+{
+ size_type cap = capacity();
+ if (len > cap || cap > 3*(len + 8))
+ {
+ TiXmlString tmp;
+ tmp.init(len);
+ memcpy(tmp.start(), str, len);
+ swap(tmp);
+ }
+ else
+ {
+ memmove(start(), str, len);
+ set_size(len);
+ }
+ return *this;
+}
+
+
+TiXmlString& TiXmlString::append(const char* str, size_type len)
+{
+ size_type newsize = length() + len;
+ if (newsize > capacity())
+ {
+ reserve (newsize + capacity());
+ }
+ memmove(finish(), str, len);
+ set_size(newsize);
+ return *this;
+}
+
+
+TiXmlString operator + (const TiXmlString & a, const TiXmlString & b)
+{
+ TiXmlString tmp;
+ tmp.reserve(a.length() + b.length());
+ tmp += a;
+ tmp += b;
+ return tmp;
+}
+
+TiXmlString operator + (const TiXmlString & a, const char* b)
+{
+ TiXmlString tmp;
+ TiXmlString::size_type b_len = static_cast<TiXmlString::size_type>( strlen(b) );
+ tmp.reserve(a.length() + b_len);
+ tmp += a;
+ tmp.append(b, b_len);
+ return tmp;
+}
+
+TiXmlString operator + (const char* a, const TiXmlString & b)
+{
+ TiXmlString tmp;
+ TiXmlString::size_type a_len = static_cast<TiXmlString::size_type>( strlen(a) );
+ tmp.reserve(a_len + b.length());
+ tmp.append(a, a_len);
+ tmp += b;
+ return tmp;
+}
+
+
+#endif // TIXML_USE_STL
diff --git a/mmc_updater/depends/tinyxml/tinystr.h b/mmc_updater/depends/tinyxml/tinystr.h
new file mode 100644
index 00000000..89cca334
--- /dev/null
+++ b/mmc_updater/depends/tinyxml/tinystr.h
@@ -0,0 +1,305 @@
+/*
+www.sourceforge.net/projects/tinyxml
+
+This software is provided 'as-is', without any express or implied
+warranty. In no event will the authors be held liable for any
+damages arising from the use of this software.
+
+Permission is granted to anyone to use this software for any
+purpose, including commercial applications, and to alter it and
+redistribute it freely, subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must
+not claim that you wrote the original software. If you use this
+software in a product, an acknowledgment in the product documentation
+would be appreciated but is not required.
+
+2. Altered source versions must be plainly marked as such, and
+must not be misrepresented as being the original software.
+
+3. This notice may not be removed or altered from any source
+distribution.
+*/
+
+
+#ifndef TIXML_USE_STL
+
+#ifndef TIXML_STRING_INCLUDED
+#define TIXML_STRING_INCLUDED
+
+#include <assert.h>
+#include <string.h>
+
+/* The support for explicit isn't that universal, and it isn't really
+ required - it is used to check that the TiXmlString class isn't incorrectly
+ used. Be nice to old compilers and macro it here:
+*/
+#if defined(_MSC_VER) && (_MSC_VER >= 1200 )
+ // Microsoft visual studio, version 6 and higher.
+ #define TIXML_EXPLICIT explicit
+#elif defined(__GNUC__) && (__GNUC__ >= 3 )
+ // GCC version 3 and higher.s
+ #define TIXML_EXPLICIT explicit
+#else
+ #define TIXML_EXPLICIT
+#endif
+
+
+/*
+ TiXmlString is an emulation of a subset of the std::string template.
+ Its purpose is to allow compiling TinyXML on compilers with no or poor STL support.
+ Only the member functions relevant to the TinyXML project have been implemented.
+ The buffer allocation is made by a simplistic power of 2 like mechanism : if we increase
+ a string and there's no more room, we allocate a buffer twice as big as we need.
+*/
+class TiXmlString
+{
+ public :
+ // The size type used
+ typedef size_t size_type;
+
+ // Error value for find primitive
+ static const size_type npos; // = -1;
+
+
+ // TiXmlString empty constructor
+ TiXmlString () : rep_(&nullrep_)
+ {
+ }
+
+ // TiXmlString copy constructor
+ TiXmlString ( const TiXmlString & copy) : rep_(0)
+ {
+ init(copy.length());
+ memcpy(start(), copy.data(), length());
+ }
+
+ // TiXmlString constructor, based on a string
+ TIXML_EXPLICIT TiXmlString ( const char * copy) : rep_(0)
+ {
+ init( static_cast<size_type>( strlen(copy) ));
+ memcpy(start(), copy, length());
+ }
+
+ // TiXmlString constructor, based on a string
+ TIXML_EXPLICIT TiXmlString ( const char * str, size_type len) : rep_(0)
+ {
+ init(len);
+ memcpy(start(), str, len);
+ }
+
+ // TiXmlString destructor
+ ~TiXmlString ()
+ {
+ quit();
+ }
+
+ TiXmlString& operator = (const char * copy)
+ {
+ return assign( copy, (size_type)strlen(copy));
+ }
+
+ TiXmlString& operator = (const TiXmlString & copy)
+ {
+ return assign(copy.start(), copy.length());
+ }
+
+
+ // += operator. Maps to append
+ TiXmlString& operator += (const char * suffix)
+ {
+ return append(suffix, static_cast<size_type>( strlen(suffix) ));
+ }
+
+ // += operator. Maps to append
+ TiXmlString& operator += (char single)
+ {
+ return append(&single, 1);
+ }
+
+ // += operator. Maps to append
+ TiXmlString& operator += (const TiXmlString & suffix)
+ {
+ return append(suffix.data(), suffix.length());
+ }
+
+
+ // Convert a TiXmlString into a null-terminated char *
+ const char * c_str () const { return rep_->str; }
+
+ // Convert a TiXmlString into a char * (need not be null terminated).
+ const char * data () const { return rep_->str; }
+
+ // Return the length of a TiXmlString
+ size_type length () const { return rep_->size; }
+
+ // Alias for length()
+ size_type size () const { return rep_->size; }
+
+ // Checks if a TiXmlString is empty
+ bool empty () const { return rep_->size == 0; }
+
+ // Return capacity of string
+ size_type capacity () const { return rep_->capacity; }
+
+
+ // single char extraction
+ const char& at (size_type index) const
+ {
+ assert( index < length() );
+ return rep_->str[ index ];
+ }
+
+ // [] operator
+ char& operator [] (size_type index) const
+ {
+ assert( index < length() );
+ return rep_->str[ index ];
+ }
+
+ // find a char in a string. Return TiXmlString::npos if not found
+ size_type find (char lookup) const
+ {
+ return find(lookup, 0);
+ }
+
+ // find a char in a string from an offset. Return TiXmlString::npos if not found
+ size_type find (char tofind, size_type offset) const
+ {
+ if (offset >= length()) return npos;
+
+ for (const char* p = c_str() + offset; *p != '\0'; ++p)
+ {
+ if (*p == tofind) return static_cast< size_type >( p - c_str() );
+ }
+ return npos;
+ }
+
+ void clear ()
+ {
+ //Lee:
+ //The original was just too strange, though correct:
+ // TiXmlString().swap(*this);
+ //Instead use the quit & re-init:
+ quit();
+ init(0,0);
+ }
+
+ /* Function to reserve a big amount of data when we know we'll need it. Be aware that this
+ function DOES NOT clear the content of the TiXmlString if any exists.
+ */
+ void reserve (size_type cap);
+
+ TiXmlString& assign (const char* str, size_type len);
+
+ TiXmlString& append (const char* str, size_type len);
+
+ void swap (TiXmlString& other)
+ {
+ Rep* r = rep_;
+ rep_ = other.rep_;
+ other.rep_ = r;
+ }
+
+ private:
+
+ void init(size_type sz) { init(sz, sz); }
+ void set_size(size_type sz) { rep_->str[ rep_->size = sz ] = '\0'; }
+ char* start() const { return rep_->str; }
+ char* finish() const { return rep_->str + rep_->size; }
+
+ struct Rep
+ {
+ size_type size, capacity;
+ char str[1];
+ };
+
+ void init(size_type sz, size_type cap)
+ {
+ if (cap)
+ {
+ // Lee: the original form:
+ // rep_ = static_cast<Rep*>(operator new(sizeof(Rep) + cap));
+ // doesn't work in some cases of new being overloaded. Switching
+ // to the normal allocation, although use an 'int' for systems
+ // that are overly picky about structure alignment.
+ const size_type bytesNeeded = sizeof(Rep) + cap;
+ const size_type intsNeeded = ( bytesNeeded + sizeof(int) - 1 ) / sizeof( int );
+ rep_ = reinterpret_cast<Rep*>( new int[ intsNeeded ] );
+
+ rep_->str[ rep_->size = sz ] = '\0';
+ rep_->capacity = cap;
+ }
+ else
+ {
+ rep_ = &nullrep_;
+ }
+ }
+
+ void quit()
+ {
+ if (rep_ != &nullrep_)
+ {
+ // The rep_ is really an array of ints. (see the allocator, above).
+ // Cast it back before delete, so the compiler won't incorrectly call destructors.
+ delete [] ( reinterpret_cast<int*>( rep_ ) );
+ }
+ }
+
+ Rep * rep_;
+ static Rep nullrep_;
+
+} ;
+
+
+inline bool operator == (const TiXmlString & a, const TiXmlString & b)
+{
+ return ( a.length() == b.length() ) // optimization on some platforms
+ && ( strcmp(a.c_str(), b.c_str()) == 0 ); // actual compare
+}
+inline bool operator < (const TiXmlString & a, const TiXmlString & b)
+{
+ return strcmp(a.c_str(), b.c_str()) < 0;
+}
+
+inline bool operator != (const TiXmlString & a, const TiXmlString & b) { return !(a == b); }
+inline bool operator > (const TiXmlString & a, const TiXmlString & b) { return b < a; }
+inline bool operator <= (const TiXmlString & a, const TiXmlString & b) { return !(b < a); }
+inline bool operator >= (const TiXmlString & a, const TiXmlString & b) { return !(a < b); }
+
+inline bool operator == (const TiXmlString & a, const char* b) { return strcmp(a.c_str(), b) == 0; }
+inline bool operator == (const char* a, const TiXmlString & b) { return b == a; }
+inline bool operator != (const TiXmlString & a, const char* b) { return !(a == b); }
+inline bool operator != (const char* a, const TiXmlString & b) { return !(b == a); }
+
+TiXmlString operator + (const TiXmlString & a, const TiXmlString & b);
+TiXmlString operator + (const TiXmlString & a, const char* b);
+TiXmlString operator + (const char* a, const TiXmlString & b);
+
+
+/*
+ TiXmlOutStream is an emulation of std::ostream. It is based on TiXmlString.
+ Only the operators that we need for TinyXML have been developped.
+*/
+class TiXmlOutStream : public TiXmlString
+{
+public :
+
+ // TiXmlOutStream << operator.
+ TiXmlOutStream & operator << (const TiXmlString & in)
+ {
+ *this += in;
+ return *this;
+ }
+
+ // TiXmlOutStream << operator.
+ TiXmlOutStream & operator << (const char * in)
+ {
+ *this += in;
+ return *this;
+ }
+
+} ;
+
+#endif // TIXML_STRING_INCLUDED
+#endif // TIXML_USE_STL
diff --git a/mmc_updater/depends/tinyxml/tinyxml.cpp b/mmc_updater/depends/tinyxml/tinyxml.cpp
new file mode 100644
index 00000000..9c161dfc
--- /dev/null
+++ b/mmc_updater/depends/tinyxml/tinyxml.cpp
@@ -0,0 +1,1886 @@
+/*
+www.sourceforge.net/projects/tinyxml
+Original code by Lee Thomason (www.grinninglizard.com)
+
+This software is provided 'as-is', without any express or implied
+warranty. In no event will the authors be held liable for any
+damages arising from the use of this software.
+
+Permission is granted to anyone to use this software for any
+purpose, including commercial applications, and to alter it and
+redistribute it freely, subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must
+not claim that you wrote the original software. If you use this
+software in a product, an acknowledgment in the product documentation
+would be appreciated but is not required.
+
+2. Altered source versions must be plainly marked as such, and
+must not be misrepresented as being the original software.
+
+3. This notice may not be removed or altered from any source
+distribution.
+*/
+
+#include <ctype.h>
+
+#ifdef TIXML_USE_STL
+#include <sstream>
+#include <iostream>
+#endif
+
+#include "tinyxml.h"
+
+FILE* TiXmlFOpen( const char* filename, const char* mode );
+
+bool TiXmlBase::condenseWhiteSpace = true;
+
+// Microsoft compiler security
+FILE* TiXmlFOpen( const char* filename, const char* mode )
+{
+ #if defined(_MSC_VER) && (_MSC_VER >= 1400 )
+ FILE* fp = 0;
+ errno_t err = fopen_s( &fp, filename, mode );
+ if ( !err && fp )
+ return fp;
+ return 0;
+ #else
+ return fopen( filename, mode );
+ #endif
+}
+
+void TiXmlBase::EncodeString( const TIXML_STRING& str, TIXML_STRING* outString )
+{
+ int i=0;
+
+ while( i<(int)str.length() )
+ {
+ unsigned char c = (unsigned char) str[i];
+
+ if ( c == '&'
+ && i < ( (int)str.length() - 2 )
+ && str[i+1] == '#'
+ && str[i+2] == 'x' )
+ {
+ // Hexadecimal character reference.
+ // Pass through unchanged.
+ // &#xA9; -- copyright symbol, for example.
+ //
+ // The -1 is a bug fix from Rob Laveaux. It keeps
+ // an overflow from happening if there is no ';'.
+ // There are actually 2 ways to exit this loop -
+ // while fails (error case) and break (semicolon found).
+ // However, there is no mechanism (currently) for
+ // this function to return an error.
+ while ( i<(int)str.length()-1 )
+ {
+ outString->append( str.c_str() + i, 1 );
+ ++i;
+ if ( str[i] == ';' )
+ break;
+ }
+ }
+ else if ( c == '&' )
+ {
+ outString->append( entity[0].str, entity[0].strLength );
+ ++i;
+ }
+ else if ( c == '<' )
+ {
+ outString->append( entity[1].str, entity[1].strLength );
+ ++i;
+ }
+ else if ( c == '>' )
+ {
+ outString->append( entity[2].str, entity[2].strLength );
+ ++i;
+ }
+ else if ( c == '\"' )
+ {
+ outString->append( entity[3].str, entity[3].strLength );
+ ++i;
+ }
+ else if ( c == '\'' )
+ {
+ outString->append( entity[4].str, entity[4].strLength );
+ ++i;
+ }
+ else if ( c < 32 )
+ {
+ // Easy pass at non-alpha/numeric/symbol
+ // Below 32 is symbolic.
+ char buf[ 32 ];
+
+ #if defined(TIXML_SNPRINTF)
+ TIXML_SNPRINTF( buf, sizeof(buf), "&#x%02X;", (unsigned) ( c & 0xff ) );
+ #else
+ sprintf( buf, "&#x%02X;", (unsigned) ( c & 0xff ) );
+ #endif
+
+ //*ME: warning C4267: convert 'size_t' to 'int'
+ //*ME: Int-Cast to make compiler happy ...
+ outString->append( buf, (int)strlen( buf ) );
+ ++i;
+ }
+ else
+ {
+ //char realc = (char) c;
+ //outString->append( &realc, 1 );
+ *outString += (char) c; // somewhat more efficient function call.
+ ++i;
+ }
+ }
+}
+
+
+TiXmlNode::TiXmlNode( NodeType _type ) : TiXmlBase()
+{
+ parent = 0;
+ type = _type;
+ firstChild = 0;
+ lastChild = 0;
+ prev = 0;
+ next = 0;
+}
+
+
+TiXmlNode::~TiXmlNode()
+{
+ TiXmlNode* node = firstChild;
+ TiXmlNode* temp = 0;
+
+ while ( node )
+ {
+ temp = node;
+ node = node->next;
+ delete temp;
+ }
+}
+
+
+void TiXmlNode::CopyTo( TiXmlNode* target ) const
+{
+ target->SetValue (value.c_str() );
+ target->userData = userData;
+ target->location = location;
+}
+
+
+void TiXmlNode::Clear()
+{
+ TiXmlNode* node = firstChild;
+ TiXmlNode* temp = 0;
+
+ while ( node )
+ {
+ temp = node;
+ node = node->next;
+ delete temp;
+ }
+
+ firstChild = 0;
+ lastChild = 0;
+}
+
+
+TiXmlNode* TiXmlNode::LinkEndChild( TiXmlNode* node )
+{
+ assert( node->parent == 0 || node->parent == this );
+ assert( node->GetDocument() == 0 || node->GetDocument() == this->GetDocument() );
+
+ if ( node->Type() == TiXmlNode::TINYXML_DOCUMENT )
+ {
+ delete node;
+ if ( GetDocument() )
+ GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN );
+ return 0;
+ }
+
+ node->parent = this;
+
+ node->prev = lastChild;
+ node->next = 0;
+
+ if ( lastChild )
+ lastChild->next = node;
+ else
+ firstChild = node; // it was an empty list.
+
+ lastChild = node;
+ return node;
+}
+
+
+TiXmlNode* TiXmlNode::InsertEndChild( const TiXmlNode& addThis )
+{
+ if ( addThis.Type() == TiXmlNode::TINYXML_DOCUMENT )
+ {
+ if ( GetDocument() )
+ GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN );
+ return 0;
+ }
+ TiXmlNode* node = addThis.Clone();
+ if ( !node )
+ return 0;
+
+ return LinkEndChild( node );
+}
+
+
+TiXmlNode* TiXmlNode::InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode& addThis )
+{
+ if ( !beforeThis || beforeThis->parent != this ) {
+ return 0;
+ }
+ if ( addThis.Type() == TiXmlNode::TINYXML_DOCUMENT )
+ {
+ if ( GetDocument() )
+ GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN );
+ return 0;
+ }
+
+ TiXmlNode* node = addThis.Clone();
+ if ( !node )
+ return 0;
+ node->parent = this;
+
+ node->next = beforeThis;
+ node->prev = beforeThis->prev;
+ if ( beforeThis->prev )
+ {
+ beforeThis->prev->next = node;
+ }
+ else
+ {
+ assert( firstChild == beforeThis );
+ firstChild = node;
+ }
+ beforeThis->prev = node;
+ return node;
+}
+
+
+TiXmlNode* TiXmlNode::InsertAfterChild( TiXmlNode* afterThis, const TiXmlNode& addThis )
+{
+ if ( !afterThis || afterThis->parent != this ) {
+ return 0;
+ }
+ if ( addThis.Type() == TiXmlNode::TINYXML_DOCUMENT )
+ {
+ if ( GetDocument() )
+ GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN );
+ return 0;
+ }
+
+ TiXmlNode* node = addThis.Clone();
+ if ( !node )
+ return 0;
+ node->parent = this;
+
+ node->prev = afterThis;
+ node->next = afterThis->next;
+ if ( afterThis->next )
+ {
+ afterThis->next->prev = node;
+ }
+ else
+ {
+ assert( lastChild == afterThis );
+ lastChild = node;
+ }
+ afterThis->next = node;
+ return node;
+}
+
+
+TiXmlNode* TiXmlNode::ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis )
+{
+ if ( !replaceThis )
+ return 0;
+
+ if ( replaceThis->parent != this )
+ return 0;
+
+ if ( withThis.ToDocument() ) {
+ // A document can never be a child. Thanks to Noam.
+ TiXmlDocument* document = GetDocument();
+ if ( document )
+ document->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN );
+ return 0;
+ }
+
+ TiXmlNode* node = withThis.Clone();
+ if ( !node )
+ return 0;
+
+ node->next = replaceThis->next;
+ node->prev = replaceThis->prev;
+
+ if ( replaceThis->next )
+ replaceThis->next->prev = node;
+ else
+ lastChild = node;
+
+ if ( replaceThis->prev )
+ replaceThis->prev->next = node;
+ else
+ firstChild = node;
+
+ delete replaceThis;
+ node->parent = this;
+ return node;
+}
+
+
+bool TiXmlNode::RemoveChild( TiXmlNode* removeThis )
+{
+ if ( !removeThis ) {
+ return false;
+ }
+
+ if ( removeThis->parent != this )
+ {
+ assert( 0 );
+ return false;
+ }
+
+ if ( removeThis->next )
+ removeThis->next->prev = removeThis->prev;
+ else
+ lastChild = removeThis->prev;
+
+ if ( removeThis->prev )
+ removeThis->prev->next = removeThis->next;
+ else
+ firstChild = removeThis->next;
+
+ delete removeThis;
+ return true;
+}
+
+const TiXmlNode* TiXmlNode::FirstChild( const char * _value ) const
+{
+ const TiXmlNode* node;
+ for ( node = firstChild; node; node = node->next )
+ {
+ if ( strcmp( node->Value(), _value ) == 0 )
+ return node;
+ }
+ return 0;
+}
+
+
+const TiXmlNode* TiXmlNode::LastChild( const char * _value ) const
+{
+ const TiXmlNode* node;
+ for ( node = lastChild; node; node = node->prev )
+ {
+ if ( strcmp( node->Value(), _value ) == 0 )
+ return node;
+ }
+ return 0;
+}
+
+
+const TiXmlNode* TiXmlNode::IterateChildren( const TiXmlNode* previous ) const
+{
+ if ( !previous )
+ {
+ return FirstChild();
+ }
+ else
+ {
+ assert( previous->parent == this );
+ return previous->NextSibling();
+ }
+}
+
+
+const TiXmlNode* TiXmlNode::IterateChildren( const char * val, const TiXmlNode* previous ) const
+{
+ if ( !previous )
+ {
+ return FirstChild( val );
+ }
+ else
+ {
+ assert( previous->parent == this );
+ return previous->NextSibling( val );
+ }
+}
+
+
+const TiXmlNode* TiXmlNode::NextSibling( const char * _value ) const
+{
+ const TiXmlNode* node;
+ for ( node = next; node; node = node->next )
+ {
+ if ( strcmp( node->Value(), _value ) == 0 )
+ return node;
+ }
+ return 0;
+}
+
+
+const TiXmlNode* TiXmlNode::PreviousSibling( const char * _value ) const
+{
+ const TiXmlNode* node;
+ for ( node = prev; node; node = node->prev )
+ {
+ if ( strcmp( node->Value(), _value ) == 0 )
+ return node;
+ }
+ return 0;
+}
+
+
+void TiXmlElement::RemoveAttribute( const char * name )
+{
+ #ifdef TIXML_USE_STL
+ TIXML_STRING str( name );
+ TiXmlAttribute* node = attributeSet.Find( str );
+ #else
+ TiXmlAttribute* node = attributeSet.Find( name );
+ #endif
+ if ( node )
+ {
+ attributeSet.Remove( node );
+ delete node;
+ }
+}
+
+const TiXmlElement* TiXmlNode::FirstChildElement() const
+{
+ const TiXmlNode* node;
+
+ for ( node = FirstChild();
+ node;
+ node = node->NextSibling() )
+ {
+ if ( node->ToElement() )
+ return node->ToElement();
+ }
+ return 0;
+}
+
+
+const TiXmlElement* TiXmlNode::FirstChildElement( const char * _value ) const
+{
+ const TiXmlNode* node;
+
+ for ( node = FirstChild( _value );
+ node;
+ node = node->NextSibling( _value ) )
+ {
+ if ( node->ToElement() )
+ return node->ToElement();
+ }
+ return 0;
+}
+
+
+const TiXmlElement* TiXmlNode::NextSiblingElement() const
+{
+ const TiXmlNode* node;
+
+ for ( node = NextSibling();
+ node;
+ node = node->NextSibling() )
+ {
+ if ( node->ToElement() )
+ return node->ToElement();
+ }
+ return 0;
+}
+
+
+const TiXmlElement* TiXmlNode::NextSiblingElement( const char * _value ) const
+{
+ const TiXmlNode* node;
+
+ for ( node = NextSibling( _value );
+ node;
+ node = node->NextSibling( _value ) )
+ {
+ if ( node->ToElement() )
+ return node->ToElement();
+ }
+ return 0;
+}
+
+
+const TiXmlDocument* TiXmlNode::GetDocument() const
+{
+ const TiXmlNode* node;
+
+ for( node = this; node; node = node->parent )
+ {
+ if ( node->ToDocument() )
+ return node->ToDocument();
+ }
+ return 0;
+}
+
+
+TiXmlElement::TiXmlElement (const char * _value)
+ : TiXmlNode( TiXmlNode::TINYXML_ELEMENT )
+{
+ firstChild = lastChild = 0;
+ value = _value;
+}
+
+
+#ifdef TIXML_USE_STL
+TiXmlElement::TiXmlElement( const std::string& _value )
+ : TiXmlNode( TiXmlNode::TINYXML_ELEMENT )
+{
+ firstChild = lastChild = 0;
+ value = _value;
+}
+#endif
+
+
+TiXmlElement::TiXmlElement( const TiXmlElement& copy)
+ : TiXmlNode( TiXmlNode::TINYXML_ELEMENT )
+{
+ firstChild = lastChild = 0;
+ copy.CopyTo( this );
+}
+
+
+TiXmlElement& TiXmlElement::operator=( const TiXmlElement& base )
+{
+ ClearThis();
+ base.CopyTo( this );
+ return *this;
+}
+
+
+TiXmlElement::~TiXmlElement()
+{
+ ClearThis();
+}
+
+
+void TiXmlElement::ClearThis()
+{
+ Clear();
+ while( attributeSet.First() )
+ {
+ TiXmlAttribute* node = attributeSet.First();
+ attributeSet.Remove( node );
+ delete node;
+ }
+}
+
+
+const char* TiXmlElement::Attribute( const char* name ) const
+{
+ const TiXmlAttribute* node = attributeSet.Find( name );
+ if ( node )
+ return node->Value();
+ return 0;
+}
+
+
+#ifdef TIXML_USE_STL
+const std::string* TiXmlElement::Attribute( const std::string& name ) const
+{
+ const TiXmlAttribute* attrib = attributeSet.Find( name );
+ if ( attrib )
+ return &attrib->ValueStr();
+ return 0;
+}
+#endif
+
+
+const char* TiXmlElement::Attribute( const char* name, int* i ) const
+{
+ const TiXmlAttribute* attrib = attributeSet.Find( name );
+ const char* result = 0;
+
+ if ( attrib ) {
+ result = attrib->Value();
+ if ( i ) {
+ attrib->QueryIntValue( i );
+ }
+ }
+ return result;
+}
+
+
+#ifdef TIXML_USE_STL
+const std::string* TiXmlElement::Attribute( const std::string& name, int* i ) const
+{
+ const TiXmlAttribute* attrib = attributeSet.Find( name );
+ const std::string* result = 0;
+
+ if ( attrib ) {
+ result = &attrib->ValueStr();
+ if ( i ) {
+ attrib->QueryIntValue( i );
+ }
+ }
+ return result;
+}
+#endif
+
+
+const char* TiXmlElement::Attribute( const char* name, double* d ) const
+{
+ const TiXmlAttribute* attrib = attributeSet.Find( name );
+ const char* result = 0;
+
+ if ( attrib ) {
+ result = attrib->Value();
+ if ( d ) {
+ attrib->QueryDoubleValue( d );
+ }
+ }
+ return result;
+}
+
+
+#ifdef TIXML_USE_STL
+const std::string* TiXmlElement::Attribute( const std::string& name, double* d ) const
+{
+ const TiXmlAttribute* attrib = attributeSet.Find( name );
+ const std::string* result = 0;
+
+ if ( attrib ) {
+ result = &attrib->ValueStr();
+ if ( d ) {
+ attrib->QueryDoubleValue( d );
+ }
+ }
+ return result;
+}
+#endif
+
+
+int TiXmlElement::QueryIntAttribute( const char* name, int* ival ) const
+{
+ const TiXmlAttribute* attrib = attributeSet.Find( name );
+ if ( !attrib )
+ return TIXML_NO_ATTRIBUTE;
+ return attrib->QueryIntValue( ival );
+}
+
+
+int TiXmlElement::QueryUnsignedAttribute( const char* name, unsigned* value ) const
+{
+ const TiXmlAttribute* node = attributeSet.Find( name );
+ if ( !node )
+ return TIXML_NO_ATTRIBUTE;
+
+ int ival = 0;
+ int result = node->QueryIntValue( &ival );
+ *value = (unsigned)ival;
+ return result;
+}
+
+
+int TiXmlElement::QueryBoolAttribute( const char* name, bool* bval ) const
+{
+ const TiXmlAttribute* node = attributeSet.Find( name );
+ if ( !node )
+ return TIXML_NO_ATTRIBUTE;
+
+ int result = TIXML_WRONG_TYPE;
+ if ( StringEqual( node->Value(), "true", true, TIXML_ENCODING_UNKNOWN )
+ || StringEqual( node->Value(), "yes", true, TIXML_ENCODING_UNKNOWN )
+ || StringEqual( node->Value(), "1", true, TIXML_ENCODING_UNKNOWN ) )
+ {
+ *bval = true;
+ result = TIXML_SUCCESS;
+ }
+ else if ( StringEqual( node->Value(), "false", true, TIXML_ENCODING_UNKNOWN )
+ || StringEqual( node->Value(), "no", true, TIXML_ENCODING_UNKNOWN )
+ || StringEqual( node->Value(), "0", true, TIXML_ENCODING_UNKNOWN ) )
+ {
+ *bval = false;
+ result = TIXML_SUCCESS;
+ }
+ return result;
+}
+
+
+
+#ifdef TIXML_USE_STL
+int TiXmlElement::QueryIntAttribute( const std::string& name, int* ival ) const
+{
+ const TiXmlAttribute* attrib = attributeSet.Find( name );
+ if ( !attrib )
+ return TIXML_NO_ATTRIBUTE;
+ return attrib->QueryIntValue( ival );
+}
+#endif
+
+
+int TiXmlElement::QueryDoubleAttribute( const char* name, double* dval ) const
+{
+ const TiXmlAttribute* attrib = attributeSet.Find( name );
+ if ( !attrib )
+ return TIXML_NO_ATTRIBUTE;
+ return attrib->QueryDoubleValue( dval );
+}
+
+
+#ifdef TIXML_USE_STL
+int TiXmlElement::QueryDoubleAttribute( const std::string& name, double* dval ) const
+{
+ const TiXmlAttribute* attrib = attributeSet.Find( name );
+ if ( !attrib )
+ return TIXML_NO_ATTRIBUTE;
+ return attrib->QueryDoubleValue( dval );
+}
+#endif
+
+
+void TiXmlElement::SetAttribute( const char * name, int val )
+{
+ TiXmlAttribute* attrib = attributeSet.FindOrCreate( name );
+ if ( attrib ) {
+ attrib->SetIntValue( val );
+ }
+}
+
+
+#ifdef TIXML_USE_STL
+void TiXmlElement::SetAttribute( const std::string& name, int val )
+{
+ TiXmlAttribute* attrib = attributeSet.FindOrCreate( name );
+ if ( attrib ) {
+ attrib->SetIntValue( val );
+ }
+}
+#endif
+
+
+void TiXmlElement::SetDoubleAttribute( const char * name, double val )
+{
+ TiXmlAttribute* attrib = attributeSet.FindOrCreate( name );
+ if ( attrib ) {
+ attrib->SetDoubleValue( val );
+ }
+}
+
+
+#ifdef TIXML_USE_STL
+void TiXmlElement::SetDoubleAttribute( const std::string& name, double val )
+{
+ TiXmlAttribute* attrib = attributeSet.FindOrCreate( name );
+ if ( attrib ) {
+ attrib->SetDoubleValue( val );
+ }
+}
+#endif
+
+
+void TiXmlElement::SetAttribute( const char * cname, const char * cvalue )
+{
+ TiXmlAttribute* attrib = attributeSet.FindOrCreate( cname );
+ if ( attrib ) {
+ attrib->SetValue( cvalue );
+ }
+}
+
+
+#ifdef TIXML_USE_STL
+void TiXmlElement::SetAttribute( const std::string& _name, const std::string& _value )
+{
+ TiXmlAttribute* attrib = attributeSet.FindOrCreate( _name );
+ if ( attrib ) {
+ attrib->SetValue( _value );
+ }
+}
+#endif
+
+
+void TiXmlElement::Print( FILE* cfile, int depth ) const
+{
+ int i;
+ assert( cfile );
+ for ( i=0; i<depth; i++ ) {
+ fprintf( cfile, " " );
+ }
+
+ fprintf( cfile, "<%s", value.c_str() );
+
+ const TiXmlAttribute* attrib;
+ for ( attrib = attributeSet.First(); attrib; attrib = attrib->Next() )
+ {
+ fprintf( cfile, " " );
+ attrib->Print( cfile, depth );
+ }
+
+ // There are 3 different formatting approaches:
+ // 1) An element without children is printed as a <foo /> node
+ // 2) An element with only a text child is printed as <foo> text </foo>
+ // 3) An element with children is printed on multiple lines.
+ TiXmlNode* node;
+ if ( !firstChild )
+ {
+ fprintf( cfile, " />" );
+ }
+ else if ( firstChild == lastChild && firstChild->ToText() )
+ {
+ fprintf( cfile, ">" );
+ firstChild->Print( cfile, depth + 1 );
+ fprintf( cfile, "</%s>", value.c_str() );
+ }
+ else
+ {
+ fprintf( cfile, ">" );
+
+ for ( node = firstChild; node; node=node->NextSibling() )
+ {
+ if ( !node->ToText() )
+ {
+ fprintf( cfile, "\n" );
+ }
+ node->Print( cfile, depth+1 );
+ }
+ fprintf( cfile, "\n" );
+ for( i=0; i<depth; ++i ) {
+ fprintf( cfile, " " );
+ }
+ fprintf( cfile, "</%s>", value.c_str() );
+ }
+}
+
+
+void TiXmlElement::CopyTo( TiXmlElement* target ) const
+{
+ // superclass:
+ TiXmlNode::CopyTo( target );
+
+ // Element class:
+ // Clone the attributes, then clone the children.
+ const TiXmlAttribute* attribute = 0;
+ for( attribute = attributeSet.First();
+ attribute;
+ attribute = attribute->Next() )
+ {
+ target->SetAttribute( attribute->Name(), attribute->Value() );
+ }
+
+ TiXmlNode* node = 0;
+ for ( node = firstChild; node; node = node->NextSibling() )
+ {
+ target->LinkEndChild( node->Clone() );
+ }
+}
+
+bool TiXmlElement::Accept( TiXmlVisitor* visitor ) const
+{
+ if ( visitor->VisitEnter( *this, attributeSet.First() ) )
+ {
+ for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() )
+ {
+ if ( !node->Accept( visitor ) )
+ break;
+ }
+ }
+ return visitor->VisitExit( *this );
+}
+
+
+TiXmlNode* TiXmlElement::Clone() const
+{
+ TiXmlElement* clone = new TiXmlElement( Value() );
+ if ( !clone )
+ return 0;
+
+ CopyTo( clone );
+ return clone;
+}
+
+
+const char* TiXmlElement::GetText() const
+{
+ const TiXmlNode* child = this->FirstChild();
+ if ( child ) {
+ const TiXmlText* childText = child->ToText();
+ if ( childText ) {
+ return childText->Value();
+ }
+ }
+ return 0;
+}
+
+
+TiXmlDocument::TiXmlDocument() : TiXmlNode( TiXmlNode::TINYXML_DOCUMENT )
+{
+ tabsize = 4;
+ useMicrosoftBOM = false;
+ ClearError();
+}
+
+TiXmlDocument::TiXmlDocument( const char * documentName ) : TiXmlNode( TiXmlNode::TINYXML_DOCUMENT )
+{
+ tabsize = 4;
+ useMicrosoftBOM = false;
+ value = documentName;
+ ClearError();
+}
+
+
+#ifdef TIXML_USE_STL
+TiXmlDocument::TiXmlDocument( const std::string& documentName ) : TiXmlNode( TiXmlNode::TINYXML_DOCUMENT )
+{
+ tabsize = 4;
+ useMicrosoftBOM = false;
+ value = documentName;
+ ClearError();
+}
+#endif
+
+
+TiXmlDocument::TiXmlDocument( const TiXmlDocument& copy ) : TiXmlNode( TiXmlNode::TINYXML_DOCUMENT )
+{
+ copy.CopyTo( this );
+}
+
+
+TiXmlDocument& TiXmlDocument::operator=( const TiXmlDocument& copy )
+{
+ Clear();
+ copy.CopyTo( this );
+ return *this;
+}
+
+
+bool TiXmlDocument::LoadFile( TiXmlEncoding encoding )
+{
+ return LoadFile( Value(), encoding );
+}
+
+
+bool TiXmlDocument::SaveFile() const
+{
+ return SaveFile( Value() );
+}
+
+bool TiXmlDocument::LoadFile( const char* _filename, TiXmlEncoding encoding )
+{
+ TIXML_STRING filename( _filename );
+ value = filename;
+
+ // reading in binary mode so that tinyxml can normalize the EOL
+ FILE* file = TiXmlFOpen( value.c_str (), "rb" );
+
+ if ( file )
+ {
+ bool result = LoadFile( file, encoding );
+ fclose( file );
+ return result;
+ }
+ else
+ {
+ SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN );
+ return false;
+ }
+}
+
+bool TiXmlDocument::LoadFile( FILE* file, TiXmlEncoding encoding )
+{
+ if ( !file )
+ {
+ SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN );
+ return false;
+ }
+
+ // Delete the existing data:
+ Clear();
+ location.Clear();
+
+ // Get the file size, so we can pre-allocate the string. HUGE speed impact.
+ long length = 0;
+ fseek( file, 0, SEEK_END );
+ length = ftell( file );
+ fseek( file, 0, SEEK_SET );
+
+ // Strange case, but good to handle up front.
+ if ( length <= 0 )
+ {
+ SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN );
+ return false;
+ }
+
+ // Subtle bug here. TinyXml did use fgets. But from the XML spec:
+ // 2.11 End-of-Line Handling
+ // <snip>
+ // <quote>
+ // ...the XML processor MUST behave as if it normalized all line breaks in external
+ // parsed entities (including the document entity) on input, before parsing, by translating
+ // both the two-character sequence #xD #xA and any #xD that is not followed by #xA to
+ // a single #xA character.
+ // </quote>
+ //
+ // It is not clear fgets does that, and certainly isn't clear it works cross platform.
+ // Generally, you expect fgets to translate from the convention of the OS to the c/unix
+ // convention, and not work generally.
+
+ /*
+ while( fgets( buf, sizeof(buf), file ) )
+ {
+ data += buf;
+ }
+ */
+
+ char* buf = new char[ length+1 ];
+ buf[0] = 0;
+
+ if ( fread( buf, length, 1, file ) != 1 ) {
+ delete [] buf;
+ SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN );
+ return false;
+ }
+
+ // Process the buffer in place to normalize new lines. (See comment above.)
+ // Copies from the 'p' to 'q' pointer, where p can advance faster if
+ // a newline-carriage return is hit.
+ //
+ // Wikipedia:
+ // Systems based on ASCII or a compatible character set use either LF (Line feed, '\n', 0x0A, 10 in decimal) or
+ // CR (Carriage return, '\r', 0x0D, 13 in decimal) individually, or CR followed by LF (CR+LF, 0x0D 0x0A)...
+ // * LF: Multics, Unix and Unix-like systems (GNU/Linux, AIX, Xenix, Mac OS X, FreeBSD, etc.), BeOS, Amiga, RISC OS, and others
+ // * CR+LF: DEC RT-11 and most other early non-Unix, non-IBM OSes, CP/M, MP/M, DOS, OS/2, Microsoft Windows, Symbian OS
+ // * CR: Commodore 8-bit machines, Apple II family, Mac OS up to version 9 and OS-9
+
+ const char* p = buf; // the read head
+ char* q = buf; // the write head
+ const char CR = 0x0d;
+ const char LF = 0x0a;
+
+ buf[length] = 0;
+ while( *p ) {
+ assert( p < (buf+length) );
+ assert( q <= (buf+length) );
+ assert( q <= p );
+
+ if ( *p == CR ) {
+ *q++ = LF;
+ p++;
+ if ( *p == LF ) { // check for CR+LF (and skip LF)
+ p++;
+ }
+ }
+ else {
+ *q++ = *p++;
+ }
+ }
+ assert( q <= (buf+length) );
+ *q = 0;
+
+ Parse( buf, 0, encoding );
+
+ delete [] buf;
+ return !Error();
+}
+
+
+bool TiXmlDocument::SaveFile( const char * filename ) const
+{
+ // The old c stuff lives on...
+ FILE* fp = TiXmlFOpen( filename, "w" );
+ if ( fp )
+ {
+ bool result = SaveFile( fp );
+ fclose( fp );
+ return result;
+ }
+ return false;
+}
+
+
+bool TiXmlDocument::SaveFile( FILE* fp ) const
+{
+ if ( useMicrosoftBOM )
+ {
+ const unsigned char TIXML_UTF_LEAD_0 = 0xefU;
+ const unsigned char TIXML_UTF_LEAD_1 = 0xbbU;
+ const unsigned char TIXML_UTF_LEAD_2 = 0xbfU;
+
+ fputc( TIXML_UTF_LEAD_0, fp );
+ fputc( TIXML_UTF_LEAD_1, fp );
+ fputc( TIXML_UTF_LEAD_2, fp );
+ }
+ Print( fp, 0 );
+ return (ferror(fp) == 0);
+}
+
+
+void TiXmlDocument::CopyTo( TiXmlDocument* target ) const
+{
+ TiXmlNode::CopyTo( target );
+
+ target->error = error;
+ target->errorId = errorId;
+ target->errorDesc = errorDesc;
+ target->tabsize = tabsize;
+ target->errorLocation = errorLocation;
+ target->useMicrosoftBOM = useMicrosoftBOM;
+
+ TiXmlNode* node = 0;
+ for ( node = firstChild; node; node = node->NextSibling() )
+ {
+ target->LinkEndChild( node->Clone() );
+ }
+}
+
+
+TiXmlNode* TiXmlDocument::Clone() const
+{
+ TiXmlDocument* clone = new TiXmlDocument();
+ if ( !clone )
+ return 0;
+
+ CopyTo( clone );
+ return clone;
+}
+
+
+void TiXmlDocument::Print( FILE* cfile, int depth ) const
+{
+ assert( cfile );
+ for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() )
+ {
+ node->Print( cfile, depth );
+ fprintf( cfile, "\n" );
+ }
+}
+
+
+bool TiXmlDocument::Accept( TiXmlVisitor* visitor ) const
+{
+ if ( visitor->VisitEnter( *this ) )
+ {
+ for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() )
+ {
+ if ( !node->Accept( visitor ) )
+ break;
+ }
+ }
+ return visitor->VisitExit( *this );
+}
+
+
+const TiXmlAttribute* TiXmlAttribute::Next() const
+{
+ // We are using knowledge of the sentinel. The sentinel
+ // have a value or name.
+ if ( next->value.empty() && next->name.empty() )
+ return 0;
+ return next;
+}
+
+/*
+TiXmlAttribute* TiXmlAttribute::Next()
+{
+ // We are using knowledge of the sentinel. The sentinel
+ // have a value or name.
+ if ( next->value.empty() && next->name.empty() )
+ return 0;
+ return next;
+}
+*/
+
+const TiXmlAttribute* TiXmlAttribute::Previous() const
+{
+ // We are using knowledge of the sentinel. The sentinel
+ // have a value or name.
+ if ( prev->value.empty() && prev->name.empty() )
+ return 0;
+ return prev;
+}
+
+/*
+TiXmlAttribute* TiXmlAttribute::Previous()
+{
+ // We are using knowledge of the sentinel. The sentinel
+ // have a value or name.
+ if ( prev->value.empty() && prev->name.empty() )
+ return 0;
+ return prev;
+}
+*/
+
+void TiXmlAttribute::Print( FILE* cfile, int /*depth*/, TIXML_STRING* str ) const
+{
+ TIXML_STRING n, v;
+
+ EncodeString( name, &n );
+ EncodeString( value, &v );
+
+ if (value.find ('\"') == TIXML_STRING::npos) {
+ if ( cfile ) {
+ fprintf (cfile, "%s=\"%s\"", n.c_str(), v.c_str() );
+ }
+ if ( str ) {
+ (*str) += n; (*str) += "=\""; (*str) += v; (*str) += "\"";
+ }
+ }
+ else {
+ if ( cfile ) {
+ fprintf (cfile, "%s='%s'", n.c_str(), v.c_str() );
+ }
+ if ( str ) {
+ (*str) += n; (*str) += "='"; (*str) += v; (*str) += "'";
+ }
+ }
+}
+
+
+int TiXmlAttribute::QueryIntValue( int* ival ) const
+{
+ if ( TIXML_SSCANF( value.c_str(), "%d", ival ) == 1 )
+ return TIXML_SUCCESS;
+ return TIXML_WRONG_TYPE;
+}
+
+int TiXmlAttribute::QueryDoubleValue( double* dval ) const
+{
+ if ( TIXML_SSCANF( value.c_str(), "%lf", dval ) == 1 )
+ return TIXML_SUCCESS;
+ return TIXML_WRONG_TYPE;
+}
+
+void TiXmlAttribute::SetIntValue( int _value )
+{
+ char buf [64];
+ #if defined(TIXML_SNPRINTF)
+ TIXML_SNPRINTF(buf, sizeof(buf), "%d", _value);
+ #else
+ sprintf (buf, "%d", _value);
+ #endif
+ SetValue (buf);
+}
+
+void TiXmlAttribute::SetDoubleValue( double _value )
+{
+ char buf [256];
+ #if defined(TIXML_SNPRINTF)
+ TIXML_SNPRINTF( buf, sizeof(buf), "%g", _value);
+ #else
+ sprintf (buf, "%g", _value);
+ #endif
+ SetValue (buf);
+}
+
+int TiXmlAttribute::IntValue() const
+{
+ return atoi (value.c_str ());
+}
+
+double TiXmlAttribute::DoubleValue() const
+{
+ return atof (value.c_str ());
+}
+
+
+TiXmlComment::TiXmlComment( const TiXmlComment& copy ) : TiXmlNode( TiXmlNode::TINYXML_COMMENT )
+{
+ copy.CopyTo( this );
+}
+
+
+TiXmlComment& TiXmlComment::operator=( const TiXmlComment& base )
+{
+ Clear();
+ base.CopyTo( this );
+ return *this;
+}
+
+
+void TiXmlComment::Print( FILE* cfile, int depth ) const
+{
+ assert( cfile );
+ for ( int i=0; i<depth; i++ )
+ {
+ fprintf( cfile, " " );
+ }
+ fprintf( cfile, "<!--%s-->", value.c_str() );
+}
+
+
+void TiXmlComment::CopyTo( TiXmlComment* target ) const
+{
+ TiXmlNode::CopyTo( target );
+}
+
+
+bool TiXmlComment::Accept( TiXmlVisitor* visitor ) const
+{
+ return visitor->Visit( *this );
+}
+
+
+TiXmlNode* TiXmlComment::Clone() const
+{
+ TiXmlComment* clone = new TiXmlComment();
+
+ if ( !clone )
+ return 0;
+
+ CopyTo( clone );
+ return clone;
+}
+
+
+void TiXmlText::Print( FILE* cfile, int depth ) const
+{
+ assert( cfile );
+ if ( cdata )
+ {
+ int i;
+ fprintf( cfile, "\n" );
+ for ( i=0; i<depth; i++ ) {
+ fprintf( cfile, " " );
+ }
+ fprintf( cfile, "<![CDATA[%s]]>\n", value.c_str() ); // unformatted output
+ }
+ else
+ {
+ TIXML_STRING buffer;
+ EncodeString( value, &buffer );
+ fprintf( cfile, "%s", buffer.c_str() );
+ }
+}
+
+
+void TiXmlText::CopyTo( TiXmlText* target ) const
+{
+ TiXmlNode::CopyTo( target );
+ target->cdata = cdata;
+}
+
+
+bool TiXmlText::Accept( TiXmlVisitor* visitor ) const
+{
+ return visitor->Visit( *this );
+}
+
+
+TiXmlNode* TiXmlText::Clone() const
+{
+ TiXmlText* clone = 0;
+ clone = new TiXmlText( "" );
+
+ if ( !clone )
+ return 0;
+
+ CopyTo( clone );
+ return clone;
+}
+
+
+TiXmlDeclaration::TiXmlDeclaration( const char * _version,
+ const char * _encoding,
+ const char * _standalone )
+ : TiXmlNode( TiXmlNode::TINYXML_DECLARATION )
+{
+ version = _version;
+ encoding = _encoding;
+ standalone = _standalone;
+}
+
+
+#ifdef TIXML_USE_STL
+TiXmlDeclaration::TiXmlDeclaration( const std::string& _version,
+ const std::string& _encoding,
+ const std::string& _standalone )
+ : TiXmlNode( TiXmlNode::TINYXML_DECLARATION )
+{
+ version = _version;
+ encoding = _encoding;
+ standalone = _standalone;
+}
+#endif
+
+
+TiXmlDeclaration::TiXmlDeclaration( const TiXmlDeclaration& copy )
+ : TiXmlNode( TiXmlNode::TINYXML_DECLARATION )
+{
+ copy.CopyTo( this );
+}
+
+
+TiXmlDeclaration& TiXmlDeclaration::operator=( const TiXmlDeclaration& copy )
+{
+ Clear();
+ copy.CopyTo( this );
+ return *this;
+}
+
+
+void TiXmlDeclaration::Print( FILE* cfile, int /*depth*/, TIXML_STRING* str ) const
+{
+ if ( cfile ) fprintf( cfile, "<?xml " );
+ if ( str ) (*str) += "<?xml ";
+
+ if ( !version.empty() ) {
+ if ( cfile ) fprintf (cfile, "version=\"%s\" ", version.c_str ());
+ if ( str ) { (*str) += "version=\""; (*str) += version; (*str) += "\" "; }
+ }
+ if ( !encoding.empty() ) {
+ if ( cfile ) fprintf (cfile, "encoding=\"%s\" ", encoding.c_str ());
+ if ( str ) { (*str) += "encoding=\""; (*str) += encoding; (*str) += "\" "; }
+ }
+ if ( !standalone.empty() ) {
+ if ( cfile ) fprintf (cfile, "standalone=\"%s\" ", standalone.c_str ());
+ if ( str ) { (*str) += "standalone=\""; (*str) += standalone; (*str) += "\" "; }
+ }
+ if ( cfile ) fprintf( cfile, "?>" );
+ if ( str ) (*str) += "?>";
+}
+
+
+void TiXmlDeclaration::CopyTo( TiXmlDeclaration* target ) const
+{
+ TiXmlNode::CopyTo( target );
+
+ target->version = version;
+ target->encoding = encoding;
+ target->standalone = standalone;
+}
+
+
+bool TiXmlDeclaration::Accept( TiXmlVisitor* visitor ) const
+{
+ return visitor->Visit( *this );
+}
+
+
+TiXmlNode* TiXmlDeclaration::Clone() const
+{
+ TiXmlDeclaration* clone = new TiXmlDeclaration();
+
+ if ( !clone )
+ return 0;
+
+ CopyTo( clone );
+ return clone;
+}
+
+
+void TiXmlUnknown::Print( FILE* cfile, int depth ) const
+{
+ for ( int i=0; i<depth; i++ )
+ fprintf( cfile, " " );
+ fprintf( cfile, "<%s>", value.c_str() );
+}
+
+
+void TiXmlUnknown::CopyTo( TiXmlUnknown* target ) const
+{
+ TiXmlNode::CopyTo( target );
+}
+
+
+bool TiXmlUnknown::Accept( TiXmlVisitor* visitor ) const
+{
+ return visitor->Visit( *this );
+}
+
+
+TiXmlNode* TiXmlUnknown::Clone() const
+{
+ TiXmlUnknown* clone = new TiXmlUnknown();
+
+ if ( !clone )
+ return 0;
+
+ CopyTo( clone );
+ return clone;
+}
+
+
+TiXmlAttributeSet::TiXmlAttributeSet()
+{
+ sentinel.next = &sentinel;
+ sentinel.prev = &sentinel;
+}
+
+
+TiXmlAttributeSet::~TiXmlAttributeSet()
+{
+ assert( sentinel.next == &sentinel );
+ assert( sentinel.prev == &sentinel );
+}
+
+
+void TiXmlAttributeSet::Add( TiXmlAttribute* addMe )
+{
+ #ifdef TIXML_USE_STL
+ assert( !Find( TIXML_STRING( addMe->Name() ) ) ); // Shouldn't be multiply adding to the set.
+ #else
+ assert( !Find( addMe->Name() ) ); // Shouldn't be multiply adding to the set.
+ #endif
+
+ addMe->next = &sentinel;
+ addMe->prev = sentinel.prev;
+
+ sentinel.prev->next = addMe;
+ sentinel.prev = addMe;
+}
+
+void TiXmlAttributeSet::Remove( TiXmlAttribute* removeMe )
+{
+ TiXmlAttribute* node;
+
+ for( node = sentinel.next; node != &sentinel; node = node->next )
+ {
+ if ( node == removeMe )
+ {
+ node->prev->next = node->next;
+ node->next->prev = node->prev;
+ node->next = 0;
+ node->prev = 0;
+ return;
+ }
+ }
+ assert( 0 ); // we tried to remove a non-linked attribute.
+}
+
+
+#ifdef TIXML_USE_STL
+TiXmlAttribute* TiXmlAttributeSet::Find( const std::string& name ) const
+{
+ for( TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next )
+ {
+ if ( node->name == name )
+ return node;
+ }
+ return 0;
+}
+
+TiXmlAttribute* TiXmlAttributeSet::FindOrCreate( const std::string& _name )
+{
+ TiXmlAttribute* attrib = Find( _name );
+ if ( !attrib ) {
+ attrib = new TiXmlAttribute();
+ Add( attrib );
+ attrib->SetName( _name );
+ }
+ return attrib;
+}
+#endif
+
+
+TiXmlAttribute* TiXmlAttributeSet::Find( const char* name ) const
+{
+ for( TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next )
+ {
+ if ( strcmp( node->name.c_str(), name ) == 0 )
+ return node;
+ }
+ return 0;
+}
+
+
+TiXmlAttribute* TiXmlAttributeSet::FindOrCreate( const char* _name )
+{
+ TiXmlAttribute* attrib = Find( _name );
+ if ( !attrib ) {
+ attrib = new TiXmlAttribute();
+ Add( attrib );
+ attrib->SetName( _name );
+ }
+ return attrib;
+}
+
+
+#ifdef TIXML_USE_STL
+std::istream& operator>> (std::istream & in, TiXmlNode & base)
+{
+ TIXML_STRING tag;
+ tag.reserve( 8 * 1000 );
+ base.StreamIn( &in, &tag );
+
+ base.Parse( tag.c_str(), 0, TIXML_DEFAULT_ENCODING );
+ return in;
+}
+#endif
+
+
+#ifdef TIXML_USE_STL
+std::ostream& operator<< (std::ostream & out, const TiXmlNode & base)
+{
+ TiXmlPrinter printer;
+ printer.SetStreamPrinting();
+ base.Accept( &printer );
+ out << printer.Str();
+
+ return out;
+}
+
+
+std::string& operator<< (std::string& out, const TiXmlNode& base )
+{
+ TiXmlPrinter printer;
+ printer.SetStreamPrinting();
+ base.Accept( &printer );
+ out.append( printer.Str() );
+
+ return out;
+}
+#endif
+
+
+TiXmlHandle TiXmlHandle::FirstChild() const
+{
+ if ( node )
+ {
+ TiXmlNode* child = node->FirstChild();
+ if ( child )
+ return TiXmlHandle( child );
+ }
+ return TiXmlHandle( 0 );
+}
+
+
+TiXmlHandle TiXmlHandle::FirstChild( const char * value ) const
+{
+ if ( node )
+ {
+ TiXmlNode* child = node->FirstChild( value );
+ if ( child )
+ return TiXmlHandle( child );
+ }
+ return TiXmlHandle( 0 );
+}
+
+
+TiXmlHandle TiXmlHandle::FirstChildElement() const
+{
+ if ( node )
+ {
+ TiXmlElement* child = node->FirstChildElement();
+ if ( child )
+ return TiXmlHandle( child );
+ }
+ return TiXmlHandle( 0 );
+}
+
+
+TiXmlHandle TiXmlHandle::FirstChildElement( const char * value ) const
+{
+ if ( node )
+ {
+ TiXmlElement* child = node->FirstChildElement( value );
+ if ( child )
+ return TiXmlHandle( child );
+ }
+ return TiXmlHandle( 0 );
+}
+
+
+TiXmlHandle TiXmlHandle::Child( int count ) const
+{
+ if ( node )
+ {
+ int i;
+ TiXmlNode* child = node->FirstChild();
+ for ( i=0;
+ child && i<count;
+ child = child->NextSibling(), ++i )
+ {
+ // nothing
+ }
+ if ( child )
+ return TiXmlHandle( child );
+ }
+ return TiXmlHandle( 0 );
+}
+
+
+TiXmlHandle TiXmlHandle::Child( const char* value, int count ) const
+{
+ if ( node )
+ {
+ int i;
+ TiXmlNode* child = node->FirstChild( value );
+ for ( i=0;
+ child && i<count;
+ child = child->NextSibling( value ), ++i )
+ {
+ // nothing
+ }
+ if ( child )
+ return TiXmlHandle( child );
+ }
+ return TiXmlHandle( 0 );
+}
+
+
+TiXmlHandle TiXmlHandle::ChildElement( int count ) const
+{
+ if ( node )
+ {
+ int i;
+ TiXmlElement* child = node->FirstChildElement();
+ for ( i=0;
+ child && i<count;
+ child = child->NextSiblingElement(), ++i )
+ {
+ // nothing
+ }
+ if ( child )
+ return TiXmlHandle( child );
+ }
+ return TiXmlHandle( 0 );
+}
+
+
+TiXmlHandle TiXmlHandle::ChildElement( const char* value, int count ) const
+{
+ if ( node )
+ {
+ int i;
+ TiXmlElement* child = node->FirstChildElement( value );
+ for ( i=0;
+ child && i<count;
+ child = child->NextSiblingElement( value ), ++i )
+ {
+ // nothing
+ }
+ if ( child )
+ return TiXmlHandle( child );
+ }
+ return TiXmlHandle( 0 );
+}
+
+
+bool TiXmlPrinter::VisitEnter( const TiXmlDocument& )
+{
+ return true;
+}
+
+bool TiXmlPrinter::VisitExit( const TiXmlDocument& )
+{
+ return true;
+}
+
+bool TiXmlPrinter::VisitEnter( const TiXmlElement& element, const TiXmlAttribute* firstAttribute )
+{
+ DoIndent();
+ buffer += "<";
+ buffer += element.Value();
+
+ for( const TiXmlAttribute* attrib = firstAttribute; attrib; attrib = attrib->Next() )
+ {
+ buffer += " ";
+ attrib->Print( 0, 0, &buffer );
+ }
+
+ if ( !element.FirstChild() )
+ {
+ buffer += " />";
+ DoLineBreak();
+ }
+ else
+ {
+ buffer += ">";
+ if ( element.FirstChild()->ToText()
+ && element.LastChild() == element.FirstChild()
+ && element.FirstChild()->ToText()->CDATA() == false )
+ {
+ simpleTextPrint = true;
+ // no DoLineBreak()!
+ }
+ else
+ {
+ DoLineBreak();
+ }
+ }
+ ++depth;
+ return true;
+}
+
+
+bool TiXmlPrinter::VisitExit( const TiXmlElement& element )
+{
+ --depth;
+ if ( !element.FirstChild() )
+ {
+ // nothing.
+ }
+ else
+ {
+ if ( simpleTextPrint )
+ {
+ simpleTextPrint = false;
+ }
+ else
+ {
+ DoIndent();
+ }
+ buffer += "</";
+ buffer += element.Value();
+ buffer += ">";
+ DoLineBreak();
+ }
+ return true;
+}
+
+
+bool TiXmlPrinter::Visit( const TiXmlText& text )
+{
+ if ( text.CDATA() )
+ {
+ DoIndent();
+ buffer += "<![CDATA[";
+ buffer += text.Value();
+ buffer += "]]>";
+ DoLineBreak();
+ }
+ else if ( simpleTextPrint )
+ {
+ TIXML_STRING str;
+ TiXmlBase::EncodeString( text.ValueTStr(), &str );
+ buffer += str;
+ }
+ else
+ {
+ DoIndent();
+ TIXML_STRING str;
+ TiXmlBase::EncodeString( text.ValueTStr(), &str );
+ buffer += str;
+ DoLineBreak();
+ }
+ return true;
+}
+
+
+bool TiXmlPrinter::Visit( const TiXmlDeclaration& declaration )
+{
+ DoIndent();
+ declaration.Print( 0, 0, &buffer );
+ DoLineBreak();
+ return true;
+}
+
+
+bool TiXmlPrinter::Visit( const TiXmlComment& comment )
+{
+ DoIndent();
+ buffer += "<!--";
+ buffer += comment.Value();
+ buffer += "-->";
+ DoLineBreak();
+ return true;
+}
+
+
+bool TiXmlPrinter::Visit( const TiXmlUnknown& unknown )
+{
+ DoIndent();
+ buffer += "<";
+ buffer += unknown.Value();
+ buffer += ">";
+ DoLineBreak();
+ return true;
+}
+
diff --git a/mmc_updater/depends/tinyxml/tinyxml.h b/mmc_updater/depends/tinyxml/tinyxml.h
new file mode 100644
index 00000000..a3589e5b
--- /dev/null
+++ b/mmc_updater/depends/tinyxml/tinyxml.h
@@ -0,0 +1,1805 @@
+/*
+www.sourceforge.net/projects/tinyxml
+Original code by Lee Thomason (www.grinninglizard.com)
+
+This software is provided 'as-is', without any express or implied
+warranty. In no event will the authors be held liable for any
+damages arising from the use of this software.
+
+Permission is granted to anyone to use this software for any
+purpose, including commercial applications, and to alter it and
+redistribute it freely, subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must
+not claim that you wrote the original software. If you use this
+software in a product, an acknowledgment in the product documentation
+would be appreciated but is not required.
+
+2. Altered source versions must be plainly marked as such, and
+must not be misrepresented as being the original software.
+
+3. This notice may not be removed or altered from any source
+distribution.
+*/
+
+
+#ifndef TINYXML_INCLUDED
+#define TINYXML_INCLUDED
+
+#ifdef _MSC_VER
+#pragma warning( push )
+#pragma warning( disable : 4530 )
+#pragma warning( disable : 4786 )
+#endif
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+// Help out windows:
+#if defined( _DEBUG ) && !defined( DEBUG )
+#define DEBUG
+#endif
+
+#ifdef TIXML_USE_STL
+ #include <string>
+ #include <iostream>
+ #include <sstream>
+ #define TIXML_STRING std::string
+#else
+ #include "tinystr.h"
+ #define TIXML_STRING TiXmlString
+#endif
+
+// Deprecated library function hell. Compilers want to use the
+// new safe versions. This probably doesn't fully address the problem,
+// but it gets closer. There are too many compilers for me to fully
+// test. If you get compilation troubles, undefine TIXML_SAFE
+#define TIXML_SAFE
+
+#ifdef TIXML_SAFE
+ #if defined(_MSC_VER) && (_MSC_VER >= 1400 )
+ // Microsoft visual studio, version 2005 and higher.
+ #define TIXML_SNPRINTF _snprintf_s
+ #define TIXML_SSCANF sscanf_s
+ #elif defined(_MSC_VER) && (_MSC_VER >= 1200 )
+ // Microsoft visual studio, version 6 and higher.
+ //#pragma message( "Using _sn* functions." )
+ #define TIXML_SNPRINTF _snprintf
+ #define TIXML_SSCANF sscanf
+ #elif defined(__GNUC__) && (__GNUC__ >= 3 )
+ // GCC version 3 and higher.s
+ //#warning( "Using sn* functions." )
+ #define TIXML_SNPRINTF snprintf
+ #define TIXML_SSCANF sscanf
+ #else
+ #define TIXML_SNPRINTF snprintf
+ #define TIXML_SSCANF sscanf
+ #endif
+#endif
+
+class TiXmlDocument;
+class TiXmlElement;
+class TiXmlComment;
+class TiXmlUnknown;
+class TiXmlAttribute;
+class TiXmlText;
+class TiXmlDeclaration;
+class TiXmlParsingData;
+
+const int TIXML_MAJOR_VERSION = 2;
+const int TIXML_MINOR_VERSION = 6;
+const int TIXML_PATCH_VERSION = 2;
+
+/* Internal structure for tracking location of items
+ in the XML file.
+*/
+struct TiXmlCursor
+{
+ TiXmlCursor() { Clear(); }
+ void Clear() { row = col = -1; }
+
+ int row; // 0 based.
+ int col; // 0 based.
+};
+
+
+/**
+ Implements the interface to the "Visitor pattern" (see the Accept() method.)
+ If you call the Accept() method, it requires being passed a TiXmlVisitor
+ class to handle callbacks. For nodes that contain other nodes (Document, Element)
+ you will get called with a VisitEnter/VisitExit pair. Nodes that are always leaves
+ are simply called with Visit().
+
+ If you return 'true' from a Visit method, recursive parsing will continue. If you return
+ false, <b>no children of this node or its sibilings</b> will be Visited.
+
+ All flavors of Visit methods have a default implementation that returns 'true' (continue
+ visiting). You need to only override methods that are interesting to you.
+
+ Generally Accept() is called on the TiXmlDocument, although all nodes suppert Visiting.
+
+ You should never change the document from a callback.
+
+ @sa TiXmlNode::Accept()
+*/
+class TiXmlVisitor
+{
+public:
+ virtual ~TiXmlVisitor() {}
+
+ /// Visit a document.
+ virtual bool VisitEnter( const TiXmlDocument& /*doc*/ ) { return true; }
+ /// Visit a document.
+ virtual bool VisitExit( const TiXmlDocument& /*doc*/ ) { return true; }
+
+ /// Visit an element.
+ virtual bool VisitEnter( const TiXmlElement& /*element*/, const TiXmlAttribute* /*firstAttribute*/ ) { return true; }
+ /// Visit an element.
+ virtual bool VisitExit( const TiXmlElement& /*element*/ ) { return true; }
+
+ /// Visit a declaration
+ virtual bool Visit( const TiXmlDeclaration& /*declaration*/ ) { return true; }
+ /// Visit a text node
+ virtual bool Visit( const TiXmlText& /*text*/ ) { return true; }
+ /// Visit a comment node
+ virtual bool Visit( const TiXmlComment& /*comment*/ ) { return true; }
+ /// Visit an unknown node
+ virtual bool Visit( const TiXmlUnknown& /*unknown*/ ) { return true; }
+};
+
+// Only used by Attribute::Query functions
+enum
+{
+ TIXML_SUCCESS,
+ TIXML_NO_ATTRIBUTE,
+ TIXML_WRONG_TYPE
+};
+
+
+// Used by the parsing routines.
+enum TiXmlEncoding
+{
+ TIXML_ENCODING_UNKNOWN,
+ TIXML_ENCODING_UTF8,
+ TIXML_ENCODING_LEGACY
+};
+
+const TiXmlEncoding TIXML_DEFAULT_ENCODING = TIXML_ENCODING_UNKNOWN;
+
+/** TiXmlBase is a base class for every class in TinyXml.
+ It does little except to establish that TinyXml classes
+ can be printed and provide some utility functions.
+
+ In XML, the document and elements can contain
+ other elements and other types of nodes.
+
+ @verbatim
+ A Document can contain: Element (container or leaf)
+ Comment (leaf)
+ Unknown (leaf)
+ Declaration( leaf )
+
+ An Element can contain: Element (container or leaf)
+ Text (leaf)
+ Attributes (not on tree)
+ Comment (leaf)
+ Unknown (leaf)
+
+ A Decleration contains: Attributes (not on tree)
+ @endverbatim
+*/
+class TiXmlBase
+{
+ friend class TiXmlNode;
+ friend class TiXmlElement;
+ friend class TiXmlDocument;
+
+public:
+ TiXmlBase() : userData(0) {}
+ virtual ~TiXmlBase() {}
+
+ /** All TinyXml classes can print themselves to a filestream
+ or the string class (TiXmlString in non-STL mode, std::string
+ in STL mode.) Either or both cfile and str can be null.
+
+ This is a formatted print, and will insert
+ tabs and newlines.
+
+ (For an unformatted stream, use the << operator.)
+ */
+ virtual void Print( FILE* cfile, int depth ) const = 0;
+
+ /** The world does not agree on whether white space should be kept or
+ not. In order to make everyone happy, these global, static functions
+ are provided to set whether or not TinyXml will condense all white space
+ into a single space or not. The default is to condense. Note changing this
+ value is not thread safe.
+ */
+ static void SetCondenseWhiteSpace( bool condense ) { condenseWhiteSpace = condense; }
+
+ /// Return the current white space setting.
+ static bool IsWhiteSpaceCondensed() { return condenseWhiteSpace; }
+
+ /** Return the position, in the original source file, of this node or attribute.
+ The row and column are 1-based. (That is the first row and first column is
+ 1,1). If the returns values are 0 or less, then the parser does not have
+ a row and column value.
+
+ Generally, the row and column value will be set when the TiXmlDocument::Load(),
+ TiXmlDocument::LoadFile(), or any TiXmlNode::Parse() is called. It will NOT be set
+ when the DOM was created from operator>>.
+
+ The values reflect the initial load. Once the DOM is modified programmatically
+ (by adding or changing nodes and attributes) the new values will NOT update to
+ reflect changes in the document.
+
+ There is a minor performance cost to computing the row and column. Computation
+ can be disabled if TiXmlDocument::SetTabSize() is called with 0 as the value.
+
+ @sa TiXmlDocument::SetTabSize()
+ */
+ int Row() const { return location.row + 1; }
+ int Column() const { return location.col + 1; } ///< See Row()
+
+ void SetUserData( void* user ) { userData = user; } ///< Set a pointer to arbitrary user data.
+ void* GetUserData() { return userData; } ///< Get a pointer to arbitrary user data.
+ const void* GetUserData() const { return userData; } ///< Get a pointer to arbitrary user data.
+
+ // Table that returs, for a given lead byte, the total number of bytes
+ // in the UTF-8 sequence.
+ static const int utf8ByteTable[256];
+
+ virtual const char* Parse( const char* p,
+ TiXmlParsingData* data,
+ TiXmlEncoding encoding /*= TIXML_ENCODING_UNKNOWN */ ) = 0;
+
+ /** Expands entities in a string. Note this should not contian the tag's '<', '>', etc,
+ or they will be transformed into entities!
+ */
+ static void EncodeString( const TIXML_STRING& str, TIXML_STRING* out );
+
+ enum
+ {
+ TIXML_NO_ERROR = 0,
+ TIXML_ERROR,
+ TIXML_ERROR_OPENING_FILE,
+ TIXML_ERROR_PARSING_ELEMENT,
+ TIXML_ERROR_FAILED_TO_READ_ELEMENT_NAME,
+ TIXML_ERROR_READING_ELEMENT_VALUE,
+ TIXML_ERROR_READING_ATTRIBUTES,
+ TIXML_ERROR_PARSING_EMPTY,
+ TIXML_ERROR_READING_END_TAG,
+ TIXML_ERROR_PARSING_UNKNOWN,
+ TIXML_ERROR_PARSING_COMMENT,
+ TIXML_ERROR_PARSING_DECLARATION,
+ TIXML_ERROR_DOCUMENT_EMPTY,
+ TIXML_ERROR_EMBEDDED_NULL,
+ TIXML_ERROR_PARSING_CDATA,
+ TIXML_ERROR_DOCUMENT_TOP_ONLY,
+
+ TIXML_ERROR_STRING_COUNT
+ };
+
+protected:
+
+ static const char* SkipWhiteSpace( const char*, TiXmlEncoding encoding );
+
+ inline static bool IsWhiteSpace( char c )
+ {
+ return ( isspace( (unsigned char) c ) || c == '\n' || c == '\r' );
+ }
+ inline static bool IsWhiteSpace( int c )
+ {
+ if ( c < 256 )
+ return IsWhiteSpace( (char) c );
+ return false; // Again, only truly correct for English/Latin...but usually works.
+ }
+
+ #ifdef TIXML_USE_STL
+ static bool StreamWhiteSpace( std::istream * in, TIXML_STRING * tag );
+ static bool StreamTo( std::istream * in, int character, TIXML_STRING * tag );
+ #endif
+
+ /* Reads an XML name into the string provided. Returns
+ a pointer just past the last character of the name,
+ or 0 if the function has an error.
+ */
+ static const char* ReadName( const char* p, TIXML_STRING* name, TiXmlEncoding encoding );
+
+ /* Reads text. Returns a pointer past the given end tag.
+ Wickedly complex options, but it keeps the (sensitive) code in one place.
+ */
+ static const char* ReadText( const char* in, // where to start
+ TIXML_STRING* text, // the string read
+ bool ignoreWhiteSpace, // whether to keep the white space
+ const char* endTag, // what ends this text
+ bool ignoreCase, // whether to ignore case in the end tag
+ TiXmlEncoding encoding ); // the current encoding
+
+ // If an entity has been found, transform it into a character.
+ static const char* GetEntity( const char* in, char* value, int* length, TiXmlEncoding encoding );
+
+ // Get a character, while interpreting entities.
+ // The length can be from 0 to 4 bytes.
+ inline static const char* GetChar( const char* p, char* _value, int* length, TiXmlEncoding encoding )
+ {
+ assert( p );
+ if ( encoding == TIXML_ENCODING_UTF8 )
+ {
+ *length = utf8ByteTable[ *((const unsigned char*)p) ];
+ assert( *length >= 0 && *length < 5 );
+ }
+ else
+ {
+ *length = 1;
+ }
+
+ if ( *length == 1 )
+ {
+ if ( *p == '&' )
+ return GetEntity( p, _value, length, encoding );
+ *_value = *p;
+ return p+1;
+ }
+ else if ( *length )
+ {
+ //strncpy( _value, p, *length ); // lots of compilers don't like this function (unsafe),
+ // and the null terminator isn't needed
+ for( int i=0; p[i] && i<*length; ++i ) {
+ _value[i] = p[i];
+ }
+ return p + (*length);
+ }
+ else
+ {
+ // Not valid text.
+ return 0;
+ }
+ }
+
+ // Return true if the next characters in the stream are any of the endTag sequences.
+ // Ignore case only works for english, and should only be relied on when comparing
+ // to English words: StringEqual( p, "version", true ) is fine.
+ static bool StringEqual( const char* p,
+ const char* endTag,
+ bool ignoreCase,
+ TiXmlEncoding encoding );
+
+ static const char* errorString[ TIXML_ERROR_STRING_COUNT ];
+
+ TiXmlCursor location;
+
+ /// Field containing a generic user pointer
+ void* userData;
+
+ // None of these methods are reliable for any language except English.
+ // Good for approximation, not great for accuracy.
+ static int IsAlpha( unsigned char anyByte, TiXmlEncoding encoding );
+ static int IsAlphaNum( unsigned char anyByte, TiXmlEncoding encoding );
+ inline static int ToLower( int v, TiXmlEncoding encoding )
+ {
+ if ( encoding == TIXML_ENCODING_UTF8 )
+ {
+ if ( v < 128 ) return tolower( v );
+ return v;
+ }
+ else
+ {
+ return tolower( v );
+ }
+ }
+ static void ConvertUTF32ToUTF8( unsigned long input, char* output, int* length );
+
+private:
+ TiXmlBase( const TiXmlBase& ); // not implemented.
+ void operator=( const TiXmlBase& base ); // not allowed.
+
+ struct Entity
+ {
+ const char* str;
+ unsigned int strLength;
+ char chr;
+ };
+ enum
+ {
+ NUM_ENTITY = 5,
+ MAX_ENTITY_LENGTH = 6
+
+ };
+ static Entity entity[ NUM_ENTITY ];
+ static bool condenseWhiteSpace;
+};
+
+
+/** The parent class for everything in the Document Object Model.
+ (Except for attributes).
+ Nodes have siblings, a parent, and children. A node can be
+ in a document, or stand on its own. The type of a TiXmlNode
+ can be queried, and it can be cast to its more defined type.
+*/
+class TiXmlNode : public TiXmlBase
+{
+ friend class TiXmlDocument;
+ friend class TiXmlElement;
+
+public:
+ #ifdef TIXML_USE_STL
+
+ /** An input stream operator, for every class. Tolerant of newlines and
+ formatting, but doesn't expect them.
+ */
+ friend std::istream& operator >> (std::istream& in, TiXmlNode& base);
+
+ /** An output stream operator, for every class. Note that this outputs
+ without any newlines or formatting, as opposed to Print(), which
+ includes tabs and new lines.
+
+ The operator<< and operator>> are not completely symmetric. Writing
+ a node to a stream is very well defined. You'll get a nice stream
+ of output, without any extra whitespace or newlines.
+
+ But reading is not as well defined. (As it always is.) If you create
+ a TiXmlElement (for example) and read that from an input stream,
+ the text needs to define an element or junk will result. This is
+ true of all input streams, but it's worth keeping in mind.
+
+ A TiXmlDocument will read nodes until it reads a root element, and
+ all the children of that root element.
+ */
+ friend std::ostream& operator<< (std::ostream& out, const TiXmlNode& base);
+
+ /// Appends the XML node or attribute to a std::string.
+ friend std::string& operator<< (std::string& out, const TiXmlNode& base );
+
+ #endif
+
+ /** The types of XML nodes supported by TinyXml. (All the
+ unsupported types are picked up by UNKNOWN.)
+ */
+ enum NodeType
+ {
+ TINYXML_DOCUMENT,
+ TINYXML_ELEMENT,
+ TINYXML_COMMENT,
+ TINYXML_UNKNOWN,
+ TINYXML_TEXT,
+ TINYXML_DECLARATION,
+ TINYXML_TYPECOUNT
+ };
+
+ virtual ~TiXmlNode();
+
+ /** The meaning of 'value' changes for the specific type of
+ TiXmlNode.
+ @verbatim
+ Document: filename of the xml file
+ Element: name of the element
+ Comment: the comment text
+ Unknown: the tag contents
+ Text: the text string
+ @endverbatim
+
+ The subclasses will wrap this function.
+ */
+ const char *Value() const { return value.c_str (); }
+
+ #ifdef TIXML_USE_STL
+ /** Return Value() as a std::string. If you only use STL,
+ this is more efficient than calling Value().
+ Only available in STL mode.
+ */
+ const std::string& ValueStr() const { return value; }
+ #endif
+
+ const TIXML_STRING& ValueTStr() const { return value; }
+
+ /** Changes the value of the node. Defined as:
+ @verbatim
+ Document: filename of the xml file
+ Element: name of the element
+ Comment: the comment text
+ Unknown: the tag contents
+ Text: the text string
+ @endverbatim
+ */
+ void SetValue(const char * _value) { value = _value;}
+
+ #ifdef TIXML_USE_STL
+ /// STL std::string form.
+ void SetValue( const std::string& _value ) { value = _value; }
+ #endif
+
+ /// Delete all the children of this node. Does not affect 'this'.
+ void Clear();
+
+ /// One step up the DOM.
+ TiXmlNode* Parent() { return parent; }
+ const TiXmlNode* Parent() const { return parent; }
+
+ const TiXmlNode* FirstChild() const { return firstChild; } ///< The first child of this node. Will be null if there are no children.
+ TiXmlNode* FirstChild() { return firstChild; }
+ const TiXmlNode* FirstChild( const char * value ) const; ///< The first child of this node with the matching 'value'. Will be null if none found.
+ /// The first child of this node with the matching 'value'. Will be null if none found.
+ TiXmlNode* FirstChild( const char * _value ) {
+ // Call through to the const version - safe since nothing is changed. Exiting syntax: cast this to a const (always safe)
+ // call the method, cast the return back to non-const.
+ return const_cast< TiXmlNode* > ((const_cast< const TiXmlNode* >(this))->FirstChild( _value ));
+ }
+ const TiXmlNode* LastChild() const { return lastChild; } /// The last child of this node. Will be null if there are no children.
+ TiXmlNode* LastChild() { return lastChild; }
+
+ const TiXmlNode* LastChild( const char * value ) const; /// The last child of this node matching 'value'. Will be null if there are no children.
+ TiXmlNode* LastChild( const char * _value ) {
+ return const_cast< TiXmlNode* > ((const_cast< const TiXmlNode* >(this))->LastChild( _value ));
+ }
+
+ #ifdef TIXML_USE_STL
+ const TiXmlNode* FirstChild( const std::string& _value ) const { return FirstChild (_value.c_str ()); } ///< STL std::string form.
+ TiXmlNode* FirstChild( const std::string& _value ) { return FirstChild (_value.c_str ()); } ///< STL std::string form.
+ const TiXmlNode* LastChild( const std::string& _value ) const { return LastChild (_value.c_str ()); } ///< STL std::string form.
+ TiXmlNode* LastChild( const std::string& _value ) { return LastChild (_value.c_str ()); } ///< STL std::string form.
+ #endif
+
+ /** An alternate way to walk the children of a node.
+ One way to iterate over nodes is:
+ @verbatim
+ for( child = parent->FirstChild(); child; child = child->NextSibling() )
+ @endverbatim
+
+ IterateChildren does the same thing with the syntax:
+ @verbatim
+ child = 0;
+ while( child = parent->IterateChildren( child ) )
+ @endverbatim
+
+ IterateChildren takes the previous child as input and finds
+ the next one. If the previous child is null, it returns the
+ first. IterateChildren will return null when done.
+ */
+ const TiXmlNode* IterateChildren( const TiXmlNode* previous ) const;
+ TiXmlNode* IterateChildren( const TiXmlNode* previous ) {
+ return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->IterateChildren( previous ) );
+ }
+
+ /// This flavor of IterateChildren searches for children with a particular 'value'
+ const TiXmlNode* IterateChildren( const char * value, const TiXmlNode* previous ) const;
+ TiXmlNode* IterateChildren( const char * _value, const TiXmlNode* previous ) {
+ return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->IterateChildren( _value, previous ) );
+ }
+
+ #ifdef TIXML_USE_STL
+ const TiXmlNode* IterateChildren( const std::string& _value, const TiXmlNode* previous ) const { return IterateChildren (_value.c_str (), previous); } ///< STL std::string form.
+ TiXmlNode* IterateChildren( const std::string& _value, const TiXmlNode* previous ) { return IterateChildren (_value.c_str (), previous); } ///< STL std::string form.
+ #endif
+
+ /** Add a new node related to this. Adds a child past the LastChild.
+ Returns a pointer to the new object or NULL if an error occured.
+ */
+ TiXmlNode* InsertEndChild( const TiXmlNode& addThis );
+
+
+ /** Add a new node related to this. Adds a child past the LastChild.
+
+ NOTE: the node to be added is passed by pointer, and will be
+ henceforth owned (and deleted) by tinyXml. This method is efficient
+ and avoids an extra copy, but should be used with care as it
+ uses a different memory model than the other insert functions.
+
+ @sa InsertEndChild
+ */
+ TiXmlNode* LinkEndChild( TiXmlNode* addThis );
+
+ /** Add a new node related to this. Adds a child before the specified child.
+ Returns a pointer to the new object or NULL if an error occured.
+ */
+ TiXmlNode* InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode& addThis );
+
+ /** Add a new node related to this. Adds a child after the specified child.
+ Returns a pointer to the new object or NULL if an error occured.
+ */
+ TiXmlNode* InsertAfterChild( TiXmlNode* afterThis, const TiXmlNode& addThis );
+
+ /** Replace a child of this node.
+ Returns a pointer to the new object or NULL if an error occured.
+ */
+ TiXmlNode* ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis );
+
+ /// Delete a child of this node.
+ bool RemoveChild( TiXmlNode* removeThis );
+
+ /// Navigate to a sibling node.
+ const TiXmlNode* PreviousSibling() const { return prev; }
+ TiXmlNode* PreviousSibling() { return prev; }
+
+ /// Navigate to a sibling node.
+ const TiXmlNode* PreviousSibling( const char * ) const;
+ TiXmlNode* PreviousSibling( const char *_prev ) {
+ return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->PreviousSibling( _prev ) );
+ }
+
+ #ifdef TIXML_USE_STL
+ const TiXmlNode* PreviousSibling( const std::string& _value ) const { return PreviousSibling (_value.c_str ()); } ///< STL std::string form.
+ TiXmlNode* PreviousSibling( const std::string& _value ) { return PreviousSibling (_value.c_str ()); } ///< STL std::string form.
+ const TiXmlNode* NextSibling( const std::string& _value) const { return NextSibling (_value.c_str ()); } ///< STL std::string form.
+ TiXmlNode* NextSibling( const std::string& _value) { return NextSibling (_value.c_str ()); } ///< STL std::string form.
+ #endif
+
+ /// Navigate to a sibling node.
+ const TiXmlNode* NextSibling() const { return next; }
+ TiXmlNode* NextSibling() { return next; }
+
+ /// Navigate to a sibling node with the given 'value'.
+ const TiXmlNode* NextSibling( const char * ) const;
+ TiXmlNode* NextSibling( const char* _next ) {
+ return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->NextSibling( _next ) );
+ }
+
+ /** Convenience function to get through elements.
+ Calls NextSibling and ToElement. Will skip all non-Element
+ nodes. Returns 0 if there is not another element.
+ */
+ const TiXmlElement* NextSiblingElement() const;
+ TiXmlElement* NextSiblingElement() {
+ return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->NextSiblingElement() );
+ }
+
+ /** Convenience function to get through elements.
+ Calls NextSibling and ToElement. Will skip all non-Element
+ nodes. Returns 0 if there is not another element.
+ */
+ const TiXmlElement* NextSiblingElement( const char * ) const;
+ TiXmlElement* NextSiblingElement( const char *_next ) {
+ return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->NextSiblingElement( _next ) );
+ }
+
+ #ifdef TIXML_USE_STL
+ const TiXmlElement* NextSiblingElement( const std::string& _value) const { return NextSiblingElement (_value.c_str ()); } ///< STL std::string form.
+ TiXmlElement* NextSiblingElement( const std::string& _value) { return NextSiblingElement (_value.c_str ()); } ///< STL std::string form.
+ #endif
+
+ /// Convenience function to get through elements.
+ const TiXmlElement* FirstChildElement() const;
+ TiXmlElement* FirstChildElement() {
+ return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->FirstChildElement() );
+ }
+
+ /// Convenience function to get through elements.
+ const TiXmlElement* FirstChildElement( const char * _value ) const;
+ TiXmlElement* FirstChildElement( const char * _value ) {
+ return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->FirstChildElement( _value ) );
+ }
+
+ #ifdef TIXML_USE_STL
+ const TiXmlElement* FirstChildElement( const std::string& _value ) const { return FirstChildElement (_value.c_str ()); } ///< STL std::string form.
+ TiXmlElement* FirstChildElement( const std::string& _value ) { return FirstChildElement (_value.c_str ()); } ///< STL std::string form.
+ #endif
+
+ /** Query the type (as an enumerated value, above) of this node.
+ The possible types are: TINYXML_DOCUMENT, TINYXML_ELEMENT, TINYXML_COMMENT,
+ TINYXML_UNKNOWN, TINYXML_TEXT, and TINYXML_DECLARATION.
+ */
+ int Type() const { return type; }
+
+ /** Return a pointer to the Document this node lives in.
+ Returns null if not in a document.
+ */
+ const TiXmlDocument* GetDocument() const;
+ TiXmlDocument* GetDocument() {
+ return const_cast< TiXmlDocument* >( (const_cast< const TiXmlNode* >(this))->GetDocument() );
+ }
+
+ /// Returns true if this node has no children.
+ bool NoChildren() const { return !firstChild; }
+
+ virtual const TiXmlDocument* ToDocument() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type.
+ virtual const TiXmlElement* ToElement() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type.
+ virtual const TiXmlComment* ToComment() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type.
+ virtual const TiXmlUnknown* ToUnknown() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type.
+ virtual const TiXmlText* ToText() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type.
+ virtual const TiXmlDeclaration* ToDeclaration() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type.
+
+ virtual TiXmlDocument* ToDocument() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type.
+ virtual TiXmlElement* ToElement() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type.
+ virtual TiXmlComment* ToComment() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type.
+ virtual TiXmlUnknown* ToUnknown() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type.
+ virtual TiXmlText* ToText() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type.
+ virtual TiXmlDeclaration* ToDeclaration() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type.
+
+ /** Create an exact duplicate of this node and return it. The memory must be deleted
+ by the caller.
+ */
+ virtual TiXmlNode* Clone() const = 0;
+
+ /** Accept a hierchical visit the nodes in the TinyXML DOM. Every node in the
+ XML tree will be conditionally visited and the host will be called back
+ via the TiXmlVisitor interface.
+
+ This is essentially a SAX interface for TinyXML. (Note however it doesn't re-parse
+ the XML for the callbacks, so the performance of TinyXML is unchanged by using this
+ interface versus any other.)
+
+ The interface has been based on ideas from:
+
+ - http://www.saxproject.org/
+ - http://c2.com/cgi/wiki?HierarchicalVisitorPattern
+
+ Which are both good references for "visiting".
+
+ An example of using Accept():
+ @verbatim
+ TiXmlPrinter printer;
+ tinyxmlDoc.Accept( &printer );
+ const char* xmlcstr = printer.CStr();
+ @endverbatim
+ */
+ virtual bool Accept( TiXmlVisitor* visitor ) const = 0;
+
+protected:
+ TiXmlNode( NodeType _type );
+
+ // Copy to the allocated object. Shared functionality between Clone, Copy constructor,
+ // and the assignment operator.
+ void CopyTo( TiXmlNode* target ) const;
+
+ #ifdef TIXML_USE_STL
+ // The real work of the input operator.
+ virtual void StreamIn( std::istream* in, TIXML_STRING* tag ) = 0;
+ #endif
+
+ // Figure out what is at *p, and parse it. Returns null if it is not an xml node.
+ TiXmlNode* Identify( const char* start, TiXmlEncoding encoding );
+
+ TiXmlNode* parent;
+ NodeType type;
+
+ TiXmlNode* firstChild;
+ TiXmlNode* lastChild;
+
+ TIXML_STRING value;
+
+ TiXmlNode* prev;
+ TiXmlNode* next;
+
+private:
+ TiXmlNode( const TiXmlNode& ); // not implemented.
+ void operator=( const TiXmlNode& base ); // not allowed.
+};
+
+
+/** An attribute is a name-value pair. Elements have an arbitrary
+ number of attributes, each with a unique name.
+
+ @note The attributes are not TiXmlNodes, since they are not
+ part of the tinyXML document object model. There are other
+ suggested ways to look at this problem.
+*/
+class TiXmlAttribute : public TiXmlBase
+{
+ friend class TiXmlAttributeSet;
+
+public:
+ /// Construct an empty attribute.
+ TiXmlAttribute() : TiXmlBase()
+ {
+ document = 0;
+ prev = next = 0;
+ }
+
+ #ifdef TIXML_USE_STL
+ /// std::string constructor.
+ TiXmlAttribute( const std::string& _name, const std::string& _value )
+ {
+ name = _name;
+ value = _value;
+ document = 0;
+ prev = next = 0;
+ }
+ #endif
+
+ /// Construct an attribute with a name and value.
+ TiXmlAttribute( const char * _name, const char * _value )
+ {
+ name = _name;
+ value = _value;
+ document = 0;
+ prev = next = 0;
+ }
+
+ const char* Name() const { return name.c_str(); } ///< Return the name of this attribute.
+ const char* Value() const { return value.c_str(); } ///< Return the value of this attribute.
+ #ifdef TIXML_USE_STL
+ const std::string& ValueStr() const { return value; } ///< Return the value of this attribute.
+ #endif
+ int IntValue() const; ///< Return the value of this attribute, converted to an integer.
+ double DoubleValue() const; ///< Return the value of this attribute, converted to a double.
+
+ // Get the tinyxml string representation
+ const TIXML_STRING& NameTStr() const { return name; }
+
+ /** QueryIntValue examines the value string. It is an alternative to the
+ IntValue() method with richer error checking.
+ If the value is an integer, it is stored in 'value' and
+ the call returns TIXML_SUCCESS. If it is not
+ an integer, it returns TIXML_WRONG_TYPE.
+
+ A specialized but useful call. Note that for success it returns 0,
+ which is the opposite of almost all other TinyXml calls.
+ */
+ int QueryIntValue( int* _value ) const;
+ /// QueryDoubleValue examines the value string. See QueryIntValue().
+ int QueryDoubleValue( double* _value ) const;
+
+ void SetName( const char* _name ) { name = _name; } ///< Set the name of this attribute.
+ void SetValue( const char* _value ) { value = _value; } ///< Set the value.
+
+ void SetIntValue( int _value ); ///< Set the value from an integer.
+ void SetDoubleValue( double _value ); ///< Set the value from a double.
+
+ #ifdef TIXML_USE_STL
+ /// STL std::string form.
+ void SetName( const std::string& _name ) { name = _name; }
+ /// STL std::string form.
+ void SetValue( const std::string& _value ) { value = _value; }
+ #endif
+
+ /// Get the next sibling attribute in the DOM. Returns null at end.
+ const TiXmlAttribute* Next() const;
+ TiXmlAttribute* Next() {
+ return const_cast< TiXmlAttribute* >( (const_cast< const TiXmlAttribute* >(this))->Next() );
+ }
+
+ /// Get the previous sibling attribute in the DOM. Returns null at beginning.
+ const TiXmlAttribute* Previous() const;
+ TiXmlAttribute* Previous() {
+ return const_cast< TiXmlAttribute* >( (const_cast< const TiXmlAttribute* >(this))->Previous() );
+ }
+
+ bool operator==( const TiXmlAttribute& rhs ) const { return rhs.name == name; }
+ bool operator<( const TiXmlAttribute& rhs ) const { return name < rhs.name; }
+ bool operator>( const TiXmlAttribute& rhs ) const { return name > rhs.name; }
+
+ /* Attribute parsing starts: first letter of the name
+ returns: the next char after the value end quote
+ */
+ virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding );
+
+ // Prints this Attribute to a FILE stream.
+ virtual void Print( FILE* cfile, int depth ) const {
+ Print( cfile, depth, 0 );
+ }
+ void Print( FILE* cfile, int depth, TIXML_STRING* str ) const;
+
+ // [internal use]
+ // Set the document pointer so the attribute can report errors.
+ void SetDocument( TiXmlDocument* doc ) { document = doc; }
+
+private:
+ TiXmlAttribute( const TiXmlAttribute& ); // not implemented.
+ void operator=( const TiXmlAttribute& base ); // not allowed.
+
+ TiXmlDocument* document; // A pointer back to a document, for error reporting.
+ TIXML_STRING name;
+ TIXML_STRING value;
+ TiXmlAttribute* prev;
+ TiXmlAttribute* next;
+};
+
+
+/* A class used to manage a group of attributes.
+ It is only used internally, both by the ELEMENT and the DECLARATION.
+
+ The set can be changed transparent to the Element and Declaration
+ classes that use it, but NOT transparent to the Attribute
+ which has to implement a next() and previous() method. Which makes
+ it a bit problematic and prevents the use of STL.
+
+ This version is implemented with circular lists because:
+ - I like circular lists
+ - it demonstrates some independence from the (typical) doubly linked list.
+*/
+class TiXmlAttributeSet
+{
+public:
+ TiXmlAttributeSet();
+ ~TiXmlAttributeSet();
+
+ void Add( TiXmlAttribute* attribute );
+ void Remove( TiXmlAttribute* attribute );
+
+ const TiXmlAttribute* First() const { return ( sentinel.next == &sentinel ) ? 0 : sentinel.next; }
+ TiXmlAttribute* First() { return ( sentinel.next == &sentinel ) ? 0 : sentinel.next; }
+ const TiXmlAttribute* Last() const { return ( sentinel.prev == &sentinel ) ? 0 : sentinel.prev; }
+ TiXmlAttribute* Last() { return ( sentinel.prev == &sentinel ) ? 0 : sentinel.prev; }
+
+ TiXmlAttribute* Find( const char* _name ) const;
+ TiXmlAttribute* FindOrCreate( const char* _name );
+
+# ifdef TIXML_USE_STL
+ TiXmlAttribute* Find( const std::string& _name ) const;
+ TiXmlAttribute* FindOrCreate( const std::string& _name );
+# endif
+
+
+private:
+ //*ME: Because of hidden/disabled copy-construktor in TiXmlAttribute (sentinel-element),
+ //*ME: this class must be also use a hidden/disabled copy-constructor !!!
+ TiXmlAttributeSet( const TiXmlAttributeSet& ); // not allowed
+ void operator=( const TiXmlAttributeSet& ); // not allowed (as TiXmlAttribute)
+
+ TiXmlAttribute sentinel;
+};
+
+
+/** The element is a container class. It has a value, the element name,
+ and can contain other elements, text, comments, and unknowns.
+ Elements also contain an arbitrary number of attributes.
+*/
+class TiXmlElement : public TiXmlNode
+{
+public:
+ /// Construct an element.
+ TiXmlElement (const char * in_value);
+
+ #ifdef TIXML_USE_STL
+ /// std::string constructor.
+ TiXmlElement( const std::string& _value );
+ #endif
+
+ TiXmlElement( const TiXmlElement& );
+
+ TiXmlElement& operator=( const TiXmlElement& base );
+
+ virtual ~TiXmlElement();
+
+ /** Given an attribute name, Attribute() returns the value
+ for the attribute of that name, or null if none exists.
+ */
+ const char* Attribute( const char* name ) const;
+
+ /** Given an attribute name, Attribute() returns the value
+ for the attribute of that name, or null if none exists.
+ If the attribute exists and can be converted to an integer,
+ the integer value will be put in the return 'i', if 'i'
+ is non-null.
+ */
+ const char* Attribute( const char* name, int* i ) const;
+
+ /** Given an attribute name, Attribute() returns the value
+ for the attribute of that name, or null if none exists.
+ If the attribute exists and can be converted to an double,
+ the double value will be put in the return 'd', if 'd'
+ is non-null.
+ */
+ const char* Attribute( const char* name, double* d ) const;
+
+ /** QueryIntAttribute examines the attribute - it is an alternative to the
+ Attribute() method with richer error checking.
+ If the attribute is an integer, it is stored in 'value' and
+ the call returns TIXML_SUCCESS. If it is not
+ an integer, it returns TIXML_WRONG_TYPE. If the attribute
+ does not exist, then TIXML_NO_ATTRIBUTE is returned.
+ */
+ int QueryIntAttribute( const char* name, int* _value ) const;
+ /// QueryUnsignedAttribute examines the attribute - see QueryIntAttribute().
+ int QueryUnsignedAttribute( const char* name, unsigned* _value ) const;
+ /** QueryBoolAttribute examines the attribute - see QueryIntAttribute().
+ Note that '1', 'true', or 'yes' are considered true, while '0', 'false'
+ and 'no' are considered false.
+ */
+ int QueryBoolAttribute( const char* name, bool* _value ) const;
+ /// QueryDoubleAttribute examines the attribute - see QueryIntAttribute().
+ int QueryDoubleAttribute( const char* name, double* _value ) const;
+ /// QueryFloatAttribute examines the attribute - see QueryIntAttribute().
+ int QueryFloatAttribute( const char* name, float* _value ) const {
+ double d;
+ int result = QueryDoubleAttribute( name, &d );
+ if ( result == TIXML_SUCCESS ) {
+ *_value = (float)d;
+ }
+ return result;
+ }
+
+ #ifdef TIXML_USE_STL
+ /// QueryStringAttribute examines the attribute - see QueryIntAttribute().
+ int QueryStringAttribute( const char* name, std::string* _value ) const {
+ const char* cstr = Attribute( name );
+ if ( cstr ) {
+ *_value = std::string( cstr );
+ return TIXML_SUCCESS;
+ }
+ return TIXML_NO_ATTRIBUTE;
+ }
+
+ /** Template form of the attribute query which will try to read the
+ attribute into the specified type. Very easy, very powerful, but
+ be careful to make sure to call this with the correct type.
+
+ NOTE: This method doesn't work correctly for 'string' types that contain spaces.
+
+ @return TIXML_SUCCESS, TIXML_WRONG_TYPE, or TIXML_NO_ATTRIBUTE
+ */
+ template< typename T > int QueryValueAttribute( const std::string& name, T* outValue ) const
+ {
+ const TiXmlAttribute* node = attributeSet.Find( name );
+ if ( !node )
+ return TIXML_NO_ATTRIBUTE;
+
+ std::stringstream sstream( node->ValueStr() );
+ sstream >> *outValue;
+ if ( !sstream.fail() )
+ return TIXML_SUCCESS;
+ return TIXML_WRONG_TYPE;
+ }
+
+ int QueryValueAttribute( const std::string& name, std::string* outValue ) const
+ {
+ const TiXmlAttribute* node = attributeSet.Find( name );
+ if ( !node )
+ return TIXML_NO_ATTRIBUTE;
+ *outValue = node->ValueStr();
+ return TIXML_SUCCESS;
+ }
+ #endif
+
+ /** Sets an attribute of name to a given value. The attribute
+ will be created if it does not exist, or changed if it does.
+ */
+ void SetAttribute( const char* name, const char * _value );
+
+ #ifdef TIXML_USE_STL
+ const std::string* Attribute( const std::string& name ) const;
+ const std::string* Attribute( const std::string& name, int* i ) const;
+ const std::string* Attribute( const std::string& name, double* d ) const;
+ int QueryIntAttribute( const std::string& name, int* _value ) const;
+ int QueryDoubleAttribute( const std::string& name, double* _value ) const;
+
+ /// STL std::string form.
+ void SetAttribute( const std::string& name, const std::string& _value );
+ ///< STL std::string form.
+ void SetAttribute( const std::string& name, int _value );
+ ///< STL std::string form.
+ void SetDoubleAttribute( const std::string& name, double value );
+ #endif
+
+ /** Sets an attribute of name to a given value. The attribute
+ will be created if it does not exist, or changed if it does.
+ */
+ void SetAttribute( const char * name, int value );
+
+ /** Sets an attribute of name to a given value. The attribute
+ will be created if it does not exist, or changed if it does.
+ */
+ void SetDoubleAttribute( const char * name, double value );
+
+ /** Deletes an attribute with the given name.
+ */
+ void RemoveAttribute( const char * name );
+ #ifdef TIXML_USE_STL
+ void RemoveAttribute( const std::string& name ) { RemoveAttribute (name.c_str ()); } ///< STL std::string form.
+ #endif
+
+ const TiXmlAttribute* FirstAttribute() const { return attributeSet.First(); } ///< Access the first attribute in this element.
+ TiXmlAttribute* FirstAttribute() { return attributeSet.First(); }
+ const TiXmlAttribute* LastAttribute() const { return attributeSet.Last(); } ///< Access the last attribute in this element.
+ TiXmlAttribute* LastAttribute() { return attributeSet.Last(); }
+
+ /** Convenience function for easy access to the text inside an element. Although easy
+ and concise, GetText() is limited compared to getting the TiXmlText child
+ and accessing it directly.
+
+ If the first child of 'this' is a TiXmlText, the GetText()
+ returns the character string of the Text node, else null is returned.
+
+ This is a convenient method for getting the text of simple contained text:
+ @verbatim
+ <foo>This is text</foo>
+ const char* str = fooElement->GetText();
+ @endverbatim
+
+ 'str' will be a pointer to "This is text".
+
+ Note that this function can be misleading. If the element foo was created from
+ this XML:
+ @verbatim
+ <foo><b>This is text</b></foo>
+ @endverbatim
+
+ then the value of str would be null. The first child node isn't a text node, it is
+ another element. From this XML:
+ @verbatim
+ <foo>This is <b>text</b></foo>
+ @endverbatim
+ GetText() will return "This is ".
+
+ WARNING: GetText() accesses a child node - don't become confused with the
+ similarly named TiXmlHandle::Text() and TiXmlNode::ToText() which are
+ safe type casts on the referenced node.
+ */
+ const char* GetText() const;
+
+ /// Creates a new Element and returns it - the returned element is a copy.
+ virtual TiXmlNode* Clone() const;
+ // Print the Element to a FILE stream.
+ virtual void Print( FILE* cfile, int depth ) const;
+
+ /* Attribtue parsing starts: next char past '<'
+ returns: next char past '>'
+ */
+ virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding );
+
+ virtual const TiXmlElement* ToElement() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type.
+ virtual TiXmlElement* ToElement() { return this; } ///< Cast to a more defined type. Will return null not of the requested type.
+
+ /** Walk the XML tree visiting this node and all of its children.
+ */
+ virtual bool Accept( TiXmlVisitor* visitor ) const;
+
+protected:
+
+ void CopyTo( TiXmlElement* target ) const;
+ void ClearThis(); // like clear, but initializes 'this' object as well
+
+ // Used to be public [internal use]
+ #ifdef TIXML_USE_STL
+ virtual void StreamIn( std::istream * in, TIXML_STRING * tag );
+ #endif
+ /* [internal use]
+ Reads the "value" of the element -- another element, or text.
+ This should terminate with the current end tag.
+ */
+ const char* ReadValue( const char* in, TiXmlParsingData* prevData, TiXmlEncoding encoding );
+
+private:
+ TiXmlAttributeSet attributeSet;
+};
+
+
+/** An XML comment.
+*/
+class TiXmlComment : public TiXmlNode
+{
+public:
+ /// Constructs an empty comment.
+ TiXmlComment() : TiXmlNode( TiXmlNode::TINYXML_COMMENT ) {}
+ /// Construct a comment from text.
+ TiXmlComment( const char* _value ) : TiXmlNode( TiXmlNode::TINYXML_COMMENT ) {
+ SetValue( _value );
+ }
+ TiXmlComment( const TiXmlComment& );
+ TiXmlComment& operator=( const TiXmlComment& base );
+
+ virtual ~TiXmlComment() {}
+
+ /// Returns a copy of this Comment.
+ virtual TiXmlNode* Clone() const;
+ // Write this Comment to a FILE stream.
+ virtual void Print( FILE* cfile, int depth ) const;
+
+ /* Attribtue parsing starts: at the ! of the !--
+ returns: next char past '>'
+ */
+ virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding );
+
+ virtual const TiXmlComment* ToComment() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type.
+ virtual TiXmlComment* ToComment() { return this; } ///< Cast to a more defined type. Will return null not of the requested type.
+
+ /** Walk the XML tree visiting this node and all of its children.
+ */
+ virtual bool Accept( TiXmlVisitor* visitor ) const;
+
+protected:
+ void CopyTo( TiXmlComment* target ) const;
+
+ // used to be public
+ #ifdef TIXML_USE_STL
+ virtual void StreamIn( std::istream * in, TIXML_STRING * tag );
+ #endif
+// virtual void StreamOut( TIXML_OSTREAM * out ) const;
+
+private:
+
+};
+
+
+/** XML text. A text node can have 2 ways to output the next. "normal" output
+ and CDATA. It will default to the mode it was parsed from the XML file and
+ you generally want to leave it alone, but you can change the output mode with
+ SetCDATA() and query it with CDATA().
+*/
+class TiXmlText : public TiXmlNode
+{
+ friend class TiXmlElement;
+public:
+ /** Constructor for text element. By default, it is treated as
+ normal, encoded text. If you want it be output as a CDATA text
+ element, set the parameter _cdata to 'true'
+ */
+ TiXmlText (const char * initValue ) : TiXmlNode (TiXmlNode::TINYXML_TEXT)
+ {
+ SetValue( initValue );
+ cdata = false;
+ }
+ virtual ~TiXmlText() {}
+
+ #ifdef TIXML_USE_STL
+ /// Constructor.
+ TiXmlText( const std::string& initValue ) : TiXmlNode (TiXmlNode::TINYXML_TEXT)
+ {
+ SetValue( initValue );
+ cdata = false;
+ }
+ #endif
+
+ TiXmlText( const TiXmlText& copy ) : TiXmlNode( TiXmlNode::TINYXML_TEXT ) { copy.CopyTo( this ); }
+ TiXmlText& operator=( const TiXmlText& base ) { base.CopyTo( this ); return *this; }
+
+ // Write this text object to a FILE stream.
+ virtual void Print( FILE* cfile, int depth ) const;
+
+ /// Queries whether this represents text using a CDATA section.
+ bool CDATA() const { return cdata; }
+ /// Turns on or off a CDATA representation of text.
+ void SetCDATA( bool _cdata ) { cdata = _cdata; }
+
+ virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding );
+
+ virtual const TiXmlText* ToText() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type.
+ virtual TiXmlText* ToText() { return this; } ///< Cast to a more defined type. Will return null not of the requested type.
+
+ /** Walk the XML tree visiting this node and all of its children.
+ */
+ virtual bool Accept( TiXmlVisitor* content ) const;
+
+protected :
+ /// [internal use] Creates a new Element and returns it.
+ virtual TiXmlNode* Clone() const;
+ void CopyTo( TiXmlText* target ) const;
+
+ bool Blank() const; // returns true if all white space and new lines
+ // [internal use]
+ #ifdef TIXML_USE_STL
+ virtual void StreamIn( std::istream * in, TIXML_STRING * tag );
+ #endif
+
+private:
+ bool cdata; // true if this should be input and output as a CDATA style text element
+};
+
+
+/** In correct XML the declaration is the first entry in the file.
+ @verbatim
+ <?xml version="1.0" standalone="yes"?>
+ @endverbatim
+
+ TinyXml will happily read or write files without a declaration,
+ however. There are 3 possible attributes to the declaration:
+ version, encoding, and standalone.
+
+ Note: In this version of the code, the attributes are
+ handled as special cases, not generic attributes, simply
+ because there can only be at most 3 and they are always the same.
+*/
+class TiXmlDeclaration : public TiXmlNode
+{
+public:
+ /// Construct an empty declaration.
+ TiXmlDeclaration() : TiXmlNode( TiXmlNode::TINYXML_DECLARATION ) {}
+
+#ifdef TIXML_USE_STL
+ /// Constructor.
+ TiXmlDeclaration( const std::string& _version,
+ const std::string& _encoding,
+ const std::string& _standalone );
+#endif
+
+ /// Construct.
+ TiXmlDeclaration( const char* _version,
+ const char* _encoding,
+ const char* _standalone );
+
+ TiXmlDeclaration( const TiXmlDeclaration& copy );
+ TiXmlDeclaration& operator=( const TiXmlDeclaration& copy );
+
+ virtual ~TiXmlDeclaration() {}
+
+ /// Version. Will return an empty string if none was found.
+ const char *Version() const { return version.c_str (); }
+ /// Encoding. Will return an empty string if none was found.
+ const char *Encoding() const { return encoding.c_str (); }
+ /// Is this a standalone document?
+ const char *Standalone() const { return standalone.c_str (); }
+
+ /// Creates a copy of this Declaration and returns it.
+ virtual TiXmlNode* Clone() const;
+ // Print this declaration to a FILE stream.
+ virtual void Print( FILE* cfile, int depth, TIXML_STRING* str ) const;
+ virtual void Print( FILE* cfile, int depth ) const {
+ Print( cfile, depth, 0 );
+ }
+
+ virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding );
+
+ virtual const TiXmlDeclaration* ToDeclaration() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type.
+ virtual TiXmlDeclaration* ToDeclaration() { return this; } ///< Cast to a more defined type. Will return null not of the requested type.
+
+ /** Walk the XML tree visiting this node and all of its children.
+ */
+ virtual bool Accept( TiXmlVisitor* visitor ) const;
+
+protected:
+ void CopyTo( TiXmlDeclaration* target ) const;
+ // used to be public
+ #ifdef TIXML_USE_STL
+ virtual void StreamIn( std::istream * in, TIXML_STRING * tag );
+ #endif
+
+private:
+
+ TIXML_STRING version;
+ TIXML_STRING encoding;
+ TIXML_STRING standalone;
+};
+
+
+/** Any tag that tinyXml doesn't recognize is saved as an
+ unknown. It is a tag of text, but should not be modified.
+ It will be written back to the XML, unchanged, when the file
+ is saved.
+
+ DTD tags get thrown into TiXmlUnknowns.
+*/
+class TiXmlUnknown : public TiXmlNode
+{
+public:
+ TiXmlUnknown() : TiXmlNode( TiXmlNode::TINYXML_UNKNOWN ) {}
+ virtual ~TiXmlUnknown() {}
+
+ TiXmlUnknown( const TiXmlUnknown& copy ) : TiXmlNode( TiXmlNode::TINYXML_UNKNOWN ) { copy.CopyTo( this ); }
+ TiXmlUnknown& operator=( const TiXmlUnknown& copy ) { copy.CopyTo( this ); return *this; }
+
+ /// Creates a copy of this Unknown and returns it.
+ virtual TiXmlNode* Clone() const;
+ // Print this Unknown to a FILE stream.
+ virtual void Print( FILE* cfile, int depth ) const;
+
+ virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding );
+
+ virtual const TiXmlUnknown* ToUnknown() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type.
+ virtual TiXmlUnknown* ToUnknown() { return this; } ///< Cast to a more defined type. Will return null not of the requested type.
+
+ /** Walk the XML tree visiting this node and all of its children.
+ */
+ virtual bool Accept( TiXmlVisitor* content ) const;
+
+protected:
+ void CopyTo( TiXmlUnknown* target ) const;
+
+ #ifdef TIXML_USE_STL
+ virtual void StreamIn( std::istream * in, TIXML_STRING * tag );
+ #endif
+
+private:
+
+};
+
+
+/** Always the top level node. A document binds together all the
+ XML pieces. It can be saved, loaded, and printed to the screen.
+ The 'value' of a document node is the xml file name.
+*/
+class TiXmlDocument : public TiXmlNode
+{
+public:
+ /// Create an empty document, that has no name.
+ TiXmlDocument();
+ /// Create a document with a name. The name of the document is also the filename of the xml.
+ TiXmlDocument( const char * documentName );
+
+ #ifdef TIXML_USE_STL
+ /// Constructor.
+ TiXmlDocument( const std::string& documentName );
+ #endif
+
+ TiXmlDocument( const TiXmlDocument& copy );
+ TiXmlDocument& operator=( const TiXmlDocument& copy );
+
+ virtual ~TiXmlDocument() {}
+
+ /** Load a file using the current document value.
+ Returns true if successful. Will delete any existing
+ document data before loading.
+ */
+ bool LoadFile( TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING );
+ /// Save a file using the current document value. Returns true if successful.
+ bool SaveFile() const;
+ /// Load a file using the given filename. Returns true if successful.
+ bool LoadFile( const char * filename, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING );
+ /// Save a file using the given filename. Returns true if successful.
+ bool SaveFile( const char * filename ) const;
+ /** Load a file using the given FILE*. Returns true if successful. Note that this method
+ doesn't stream - the entire object pointed at by the FILE*
+ will be interpreted as an XML file. TinyXML doesn't stream in XML from the current
+ file location. Streaming may be added in the future.
+ */
+ bool LoadFile( FILE*, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING );
+ /// Save a file using the given FILE*. Returns true if successful.
+ bool SaveFile( FILE* ) const;
+
+ #ifdef TIXML_USE_STL
+ bool LoadFile( const std::string& filename, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ) ///< STL std::string version.
+ {
+ return LoadFile( filename.c_str(), encoding );
+ }
+ bool SaveFile( const std::string& filename ) const ///< STL std::string version.
+ {
+ return SaveFile( filename.c_str() );
+ }
+ #endif
+
+ /** Parse the given null terminated block of xml data. Passing in an encoding to this
+ method (either TIXML_ENCODING_LEGACY or TIXML_ENCODING_UTF8 will force TinyXml
+ to use that encoding, regardless of what TinyXml might otherwise try to detect.
+ */
+ virtual const char* Parse( const char* p, TiXmlParsingData* data = 0, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING );
+
+ /** Get the root element -- the only top level element -- of the document.
+ In well formed XML, there should only be one. TinyXml is tolerant of
+ multiple elements at the document level.
+ */
+ const TiXmlElement* RootElement() const { return FirstChildElement(); }
+ TiXmlElement* RootElement() { return FirstChildElement(); }
+
+ /** If an error occurs, Error will be set to true. Also,
+ - The ErrorId() will contain the integer identifier of the error (not generally useful)
+ - The ErrorDesc() method will return the name of the error. (very useful)
+ - The ErrorRow() and ErrorCol() will return the location of the error (if known)
+ */
+ bool Error() const { return error; }
+
+ /// Contains a textual (english) description of the error if one occurs.
+ const char * ErrorDesc() const { return errorDesc.c_str (); }
+
+ /** Generally, you probably want the error string ( ErrorDesc() ). But if you
+ prefer the ErrorId, this function will fetch it.
+ */
+ int ErrorId() const { return errorId; }
+
+ /** Returns the location (if known) of the error. The first column is column 1,
+ and the first row is row 1. A value of 0 means the row and column wasn't applicable
+ (memory errors, for example, have no row/column) or the parser lost the error. (An
+ error in the error reporting, in that case.)
+
+ @sa SetTabSize, Row, Column
+ */
+ int ErrorRow() const { return errorLocation.row+1; }
+ int ErrorCol() const { return errorLocation.col+1; } ///< The column where the error occured. See ErrorRow()
+
+ /** SetTabSize() allows the error reporting functions (ErrorRow() and ErrorCol())
+ to report the correct values for row and column. It does not change the output
+ or input in any way.
+
+ By calling this method, with a tab size
+ greater than 0, the row and column of each node and attribute is stored
+ when the file is loaded. Very useful for tracking the DOM back in to
+ the source file.
+
+ The tab size is required for calculating the location of nodes. If not
+ set, the default of 4 is used. The tabsize is set per document. Setting
+ the tabsize to 0 disables row/column tracking.
+
+ Note that row and column tracking is not supported when using operator>>.
+
+ The tab size needs to be enabled before the parse or load. Correct usage:
+ @verbatim
+ TiXmlDocument doc;
+ doc.SetTabSize( 8 );
+ doc.Load( "myfile.xml" );
+ @endverbatim
+
+ @sa Row, Column
+ */
+ void SetTabSize( int _tabsize ) { tabsize = _tabsize; }
+
+ int TabSize() const { return tabsize; }
+
+ /** If you have handled the error, it can be reset with this call. The error
+ state is automatically cleared if you Parse a new XML block.
+ */
+ void ClearError() { error = false;
+ errorId = 0;
+ errorDesc = "";
+ errorLocation.row = errorLocation.col = 0;
+ //errorLocation.last = 0;
+ }
+
+ /** Write the document to standard out using formatted printing ("pretty print"). */
+ void Print() const { Print( stdout, 0 ); }
+
+ /* Write the document to a string using formatted printing ("pretty print"). This
+ will allocate a character array (new char[]) and return it as a pointer. The
+ calling code pust call delete[] on the return char* to avoid a memory leak.
+ */
+ //char* PrintToMemory() const;
+
+ /// Print this Document to a FILE stream.
+ virtual void Print( FILE* cfile, int depth = 0 ) const;
+ // [internal use]
+ void SetError( int err, const char* errorLocation, TiXmlParsingData* prevData, TiXmlEncoding encoding );
+
+ virtual const TiXmlDocument* ToDocument() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type.
+ virtual TiXmlDocument* ToDocument() { return this; } ///< Cast to a more defined type. Will return null not of the requested type.
+
+ /** Walk the XML tree visiting this node and all of its children.
+ */
+ virtual bool Accept( TiXmlVisitor* content ) const;
+
+protected :
+ // [internal use]
+ virtual TiXmlNode* Clone() const;
+ #ifdef TIXML_USE_STL
+ virtual void StreamIn( std::istream * in, TIXML_STRING * tag );
+ #endif
+
+private:
+ void CopyTo( TiXmlDocument* target ) const;
+
+ bool error;
+ int errorId;
+ TIXML_STRING errorDesc;
+ int tabsize;
+ TiXmlCursor errorLocation;
+ bool useMicrosoftBOM; // the UTF-8 BOM were found when read. Note this, and try to write.
+};
+
+
+/**
+ A TiXmlHandle is a class that wraps a node pointer with null checks; this is
+ an incredibly useful thing. Note that TiXmlHandle is not part of the TinyXml
+ DOM structure. It is a separate utility class.
+
+ Take an example:
+ @verbatim
+ <Document>
+ <Element attributeA = "valueA">
+ <Child attributeB = "value1" />
+ <Child attributeB = "value2" />
+ </Element>
+ <Document>
+ @endverbatim
+
+ Assuming you want the value of "attributeB" in the 2nd "Child" element, it's very
+ easy to write a *lot* of code that looks like:
+
+ @verbatim
+ TiXmlElement* root = document.FirstChildElement( "Document" );
+ if ( root )
+ {
+ TiXmlElement* element = root->FirstChildElement( "Element" );
+ if ( element )
+ {
+ TiXmlElement* child = element->FirstChildElement( "Child" );
+ if ( child )
+ {
+ TiXmlElement* child2 = child->NextSiblingElement( "Child" );
+ if ( child2 )
+ {
+ // Finally do something useful.
+ @endverbatim
+
+ And that doesn't even cover "else" cases. TiXmlHandle addresses the verbosity
+ of such code. A TiXmlHandle checks for null pointers so it is perfectly safe
+ and correct to use:
+
+ @verbatim
+ TiXmlHandle docHandle( &document );
+ TiXmlElement* child2 = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).Child( "Child", 1 ).ToElement();
+ if ( child2 )
+ {
+ // do something useful
+ @endverbatim
+
+ Which is MUCH more concise and useful.
+
+ It is also safe to copy handles - internally they are nothing more than node pointers.
+ @verbatim
+ TiXmlHandle handleCopy = handle;
+ @endverbatim
+
+ What they should not be used for is iteration:
+
+ @verbatim
+ int i=0;
+ while ( true )
+ {
+ TiXmlElement* child = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).Child( "Child", i ).ToElement();
+ if ( !child )
+ break;
+ // do something
+ ++i;
+ }
+ @endverbatim
+
+ It seems reasonable, but it is in fact two embedded while loops. The Child method is
+ a linear walk to find the element, so this code would iterate much more than it needs
+ to. Instead, prefer:
+
+ @verbatim
+ TiXmlElement* child = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).FirstChild( "Child" ).ToElement();
+
+ for( child; child; child=child->NextSiblingElement() )
+ {
+ // do something
+ }
+ @endverbatim
+*/
+class TiXmlHandle
+{
+public:
+ /// Create a handle from any node (at any depth of the tree.) This can be a null pointer.
+ TiXmlHandle( TiXmlNode* _node ) { this->node = _node; }
+ /// Copy constructor
+ TiXmlHandle( const TiXmlHandle& ref ) { this->node = ref.node; }
+ TiXmlHandle operator=( const TiXmlHandle& ref ) { if ( &ref != this ) this->node = ref.node; return *this; }
+
+ /// Return a handle to the first child node.
+ TiXmlHandle FirstChild() const;
+ /// Return a handle to the first child node with the given name.
+ TiXmlHandle FirstChild( const char * value ) const;
+ /// Return a handle to the first child element.
+ TiXmlHandle FirstChildElement() const;
+ /// Return a handle to the first child element with the given name.
+ TiXmlHandle FirstChildElement( const char * value ) const;
+
+ /** Return a handle to the "index" child with the given name.
+ The first child is 0, the second 1, etc.
+ */
+ TiXmlHandle Child( const char* value, int index ) const;
+ /** Return a handle to the "index" child.
+ The first child is 0, the second 1, etc.
+ */
+ TiXmlHandle Child( int index ) const;
+ /** Return a handle to the "index" child element with the given name.
+ The first child element is 0, the second 1, etc. Note that only TiXmlElements
+ are indexed: other types are not counted.
+ */
+ TiXmlHandle ChildElement( const char* value, int index ) const;
+ /** Return a handle to the "index" child element.
+ The first child element is 0, the second 1, etc. Note that only TiXmlElements
+ are indexed: other types are not counted.
+ */
+ TiXmlHandle ChildElement( int index ) const;
+
+ #ifdef TIXML_USE_STL
+ TiXmlHandle FirstChild( const std::string& _value ) const { return FirstChild( _value.c_str() ); }
+ TiXmlHandle FirstChildElement( const std::string& _value ) const { return FirstChildElement( _value.c_str() ); }
+
+ TiXmlHandle Child( const std::string& _value, int index ) const { return Child( _value.c_str(), index ); }
+ TiXmlHandle ChildElement( const std::string& _value, int index ) const { return ChildElement( _value.c_str(), index ); }
+ #endif
+
+ /** Return the handle as a TiXmlNode. This may return null.
+ */
+ TiXmlNode* ToNode() const { return node; }
+ /** Return the handle as a TiXmlElement. This may return null.
+ */
+ TiXmlElement* ToElement() const { return ( ( node && node->ToElement() ) ? node->ToElement() : 0 ); }
+ /** Return the handle as a TiXmlText. This may return null.
+ */
+ TiXmlText* ToText() const { return ( ( node && node->ToText() ) ? node->ToText() : 0 ); }
+ /** Return the handle as a TiXmlUnknown. This may return null.
+ */
+ TiXmlUnknown* ToUnknown() const { return ( ( node && node->ToUnknown() ) ? node->ToUnknown() : 0 ); }
+
+ /** @deprecated use ToNode.
+ Return the handle as a TiXmlNode. This may return null.
+ */
+ TiXmlNode* Node() const { return ToNode(); }
+ /** @deprecated use ToElement.
+ Return the handle as a TiXmlElement. This may return null.
+ */
+ TiXmlElement* Element() const { return ToElement(); }
+ /** @deprecated use ToText()
+ Return the handle as a TiXmlText. This may return null.
+ */
+ TiXmlText* Text() const { return ToText(); }
+ /** @deprecated use ToUnknown()
+ Return the handle as a TiXmlUnknown. This may return null.
+ */
+ TiXmlUnknown* Unknown() const { return ToUnknown(); }
+
+private:
+ TiXmlNode* node;
+};
+
+
+/** Print to memory functionality. The TiXmlPrinter is useful when you need to:
+
+ -# Print to memory (especially in non-STL mode)
+ -# Control formatting (line endings, etc.)
+
+ When constructed, the TiXmlPrinter is in its default "pretty printing" mode.
+ Before calling Accept() you can call methods to control the printing
+ of the XML document. After TiXmlNode::Accept() is called, the printed document can
+ be accessed via the CStr(), Str(), and Size() methods.
+
+ TiXmlPrinter uses the Visitor API.
+ @verbatim
+ TiXmlPrinter printer;
+ printer.SetIndent( "\t" );
+
+ doc.Accept( &printer );
+ fprintf( stdout, "%s", printer.CStr() );
+ @endverbatim
+*/
+class TiXmlPrinter : public TiXmlVisitor
+{
+public:
+ TiXmlPrinter() : depth( 0 ), simpleTextPrint( false ),
+ buffer(), indent( " " ), lineBreak( "\n" ) {}
+
+ virtual bool VisitEnter( const TiXmlDocument& doc );
+ virtual bool VisitExit( const TiXmlDocument& doc );
+
+ virtual bool VisitEnter( const TiXmlElement& element, const TiXmlAttribute* firstAttribute );
+ virtual bool VisitExit( const TiXmlElement& element );
+
+ virtual bool Visit( const TiXmlDeclaration& declaration );
+ virtual bool Visit( const TiXmlText& text );
+ virtual bool Visit( const TiXmlComment& comment );
+ virtual bool Visit( const TiXmlUnknown& unknown );
+
+ /** Set the indent characters for printing. By default 4 spaces
+ but tab (\t) is also useful, or null/empty string for no indentation.
+ */
+ void SetIndent( const char* _indent ) { indent = _indent ? _indent : "" ; }
+ /// Query the indention string.
+ const char* Indent() { return indent.c_str(); }
+ /** Set the line breaking string. By default set to newline (\n).
+ Some operating systems prefer other characters, or can be
+ set to the null/empty string for no indenation.
+ */
+ void SetLineBreak( const char* _lineBreak ) { lineBreak = _lineBreak ? _lineBreak : ""; }
+ /// Query the current line breaking string.
+ const char* LineBreak() { return lineBreak.c_str(); }
+
+ /** Switch over to "stream printing" which is the most dense formatting without
+ linebreaks. Common when the XML is needed for network transmission.
+ */
+ void SetStreamPrinting() { indent = "";
+ lineBreak = "";
+ }
+ /// Return the result.
+ const char* CStr() { return buffer.c_str(); }
+ /// Return the length of the result string.
+ size_t Size() { return buffer.size(); }
+
+ #ifdef TIXML_USE_STL
+ /// Return the result.
+ const std::string& Str() { return buffer; }
+ #endif
+
+private:
+ void DoIndent() {
+ for( int i=0; i<depth; ++i )
+ buffer += indent;
+ }
+ void DoLineBreak() {
+ buffer += lineBreak;
+ }
+
+ int depth;
+ bool simpleTextPrint;
+ TIXML_STRING buffer;
+ TIXML_STRING indent;
+ TIXML_STRING lineBreak;
+};
+
+
+#ifdef _MSC_VER
+#pragma warning( pop )
+#endif
+
+#endif
diff --git a/mmc_updater/depends/tinyxml/tinyxmlerror.cpp b/mmc_updater/depends/tinyxml/tinyxmlerror.cpp
new file mode 100644
index 00000000..538c21d0
--- /dev/null
+++ b/mmc_updater/depends/tinyxml/tinyxmlerror.cpp
@@ -0,0 +1,52 @@
+/*
+www.sourceforge.net/projects/tinyxml
+Original code (2.0 and earlier )copyright (c) 2000-2006 Lee Thomason (www.grinninglizard.com)
+
+This software is provided 'as-is', without any express or implied
+warranty. In no event will the authors be held liable for any
+damages arising from the use of this software.
+
+Permission is granted to anyone to use this software for any
+purpose, including commercial applications, and to alter it and
+redistribute it freely, subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must
+not claim that you wrote the original software. If you use this
+software in a product, an acknowledgment in the product documentation
+would be appreciated but is not required.
+
+2. Altered source versions must be plainly marked as such, and
+must not be misrepresented as being the original software.
+
+3. This notice may not be removed or altered from any source
+distribution.
+*/
+
+#include "tinyxml.h"
+
+// The goal of the seperate error file is to make the first
+// step towards localization. tinyxml (currently) only supports
+// english error messages, but the could now be translated.
+//
+// It also cleans up the code a bit.
+//
+
+const char* TiXmlBase::errorString[ TiXmlBase::TIXML_ERROR_STRING_COUNT ] =
+{
+ "No error",
+ "Error",
+ "Failed to open file",
+ "Error parsing Element.",
+ "Failed to read Element name",
+ "Error reading Element value.",
+ "Error reading Attributes.",
+ "Error: empty tag.",
+ "Error reading end tag.",
+ "Error parsing Unknown.",
+ "Error parsing Comment.",
+ "Error parsing Declaration.",
+ "Error document empty.",
+ "Error null (0) or unexpected EOF found in input stream.",
+ "Error parsing CDATA.",
+ "Error when TiXmlDocument added to document, because TiXmlDocument can only be at the root.",
+};
diff --git a/mmc_updater/depends/tinyxml/tinyxmlparser.cpp b/mmc_updater/depends/tinyxml/tinyxmlparser.cpp
new file mode 100644
index 00000000..81b7eae9
--- /dev/null
+++ b/mmc_updater/depends/tinyxml/tinyxmlparser.cpp
@@ -0,0 +1,1638 @@
+/*
+www.sourceforge.net/projects/tinyxml
+Original code by Lee Thomason (www.grinninglizard.com)
+
+This software is provided 'as-is', without any express or implied
+warranty. In no event will the authors be held liable for any
+damages arising from the use of this software.
+
+Permission is granted to anyone to use this software for any
+purpose, including commercial applications, and to alter it and
+redistribute it freely, subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must
+not claim that you wrote the original software. If you use this
+software in a product, an acknowledgment in the product documentation
+would be appreciated but is not required.
+
+2. Altered source versions must be plainly marked as such, and
+must not be misrepresented as being the original software.
+
+3. This notice may not be removed or altered from any source
+distribution.
+*/
+
+#include <ctype.h>
+#include <stddef.h>
+
+#include "tinyxml.h"
+
+//#define DEBUG_PARSER
+#if defined( DEBUG_PARSER )
+# if defined( DEBUG ) && defined( _MSC_VER )
+# include <windows.h>
+# define TIXML_LOG OutputDebugString
+# else
+# define TIXML_LOG printf
+# endif
+#endif
+
+// Note tha "PutString" hardcodes the same list. This
+// is less flexible than it appears. Changing the entries
+// or order will break putstring.
+TiXmlBase::Entity TiXmlBase::entity[ TiXmlBase::NUM_ENTITY ] =
+{
+ { "&amp;", 5, '&' },
+ { "&lt;", 4, '<' },
+ { "&gt;", 4, '>' },
+ { "&quot;", 6, '\"' },
+ { "&apos;", 6, '\'' }
+};
+
+// Bunch of unicode info at:
+// http://www.unicode.org/faq/utf_bom.html
+// Including the basic of this table, which determines the #bytes in the
+// sequence from the lead byte. 1 placed for invalid sequences --
+// although the result will be junk, pass it through as much as possible.
+// Beware of the non-characters in UTF-8:
+// ef bb bf (Microsoft "lead bytes")
+// ef bf be
+// ef bf bf
+
+const unsigned char TIXML_UTF_LEAD_0 = 0xefU;
+const unsigned char TIXML_UTF_LEAD_1 = 0xbbU;
+const unsigned char TIXML_UTF_LEAD_2 = 0xbfU;
+
+const int TiXmlBase::utf8ByteTable[256] =
+{
+ // 0 1 2 3 4 5 6 7 8 9 a b c d e f
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x00
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x10
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x20
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x30
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x40
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x50
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x60
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x70 End of ASCII range
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x80 0x80 to 0xc1 invalid
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x90
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xa0
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xb0
+ 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xc0 0xc2 to 0xdf 2 byte
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xd0
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 0xe0 0xe0 to 0xef 3 byte
+ 4, 4, 4, 4, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // 0xf0 0xf0 to 0xf4 4 byte, 0xf5 and higher invalid
+};
+
+
+void TiXmlBase::ConvertUTF32ToUTF8( unsigned long input, char* output, int* length )
+{
+ const unsigned long BYTE_MASK = 0xBF;
+ const unsigned long BYTE_MARK = 0x80;
+ const unsigned long FIRST_BYTE_MARK[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
+
+ if (input < 0x80)
+ *length = 1;
+ else if ( input < 0x800 )
+ *length = 2;
+ else if ( input < 0x10000 )
+ *length = 3;
+ else if ( input < 0x200000 )
+ *length = 4;
+ else
+ { *length = 0; return; } // This code won't covert this correctly anyway.
+
+ output += *length;
+
+ // Scary scary fall throughs.
+ switch (*length)
+ {
+ case 4:
+ --output;
+ *output = (char)((input | BYTE_MARK) & BYTE_MASK);
+ input >>= 6;
+ case 3:
+ --output;
+ *output = (char)((input | BYTE_MARK) & BYTE_MASK);
+ input >>= 6;
+ case 2:
+ --output;
+ *output = (char)((input | BYTE_MARK) & BYTE_MASK);
+ input >>= 6;
+ case 1:
+ --output;
+ *output = (char)(input | FIRST_BYTE_MARK[*length]);
+ }
+}
+
+
+/*static*/ int TiXmlBase::IsAlpha( unsigned char anyByte, TiXmlEncoding /*encoding*/ )
+{
+ // This will only work for low-ascii, everything else is assumed to be a valid
+ // letter. I'm not sure this is the best approach, but it is quite tricky trying
+ // to figure out alhabetical vs. not across encoding. So take a very
+ // conservative approach.
+
+// if ( encoding == TIXML_ENCODING_UTF8 )
+// {
+ if ( anyByte < 127 )
+ return isalpha( anyByte );
+ else
+ return 1; // What else to do? The unicode set is huge...get the english ones right.
+// }
+// else
+// {
+// return isalpha( anyByte );
+// }
+}
+
+
+/*static*/ int TiXmlBase::IsAlphaNum( unsigned char anyByte, TiXmlEncoding /*encoding*/ )
+{
+ // This will only work for low-ascii, everything else is assumed to be a valid
+ // letter. I'm not sure this is the best approach, but it is quite tricky trying
+ // to figure out alhabetical vs. not across encoding. So take a very
+ // conservative approach.
+
+// if ( encoding == TIXML_ENCODING_UTF8 )
+// {
+ if ( anyByte < 127 )
+ return isalnum( anyByte );
+ else
+ return 1; // What else to do? The unicode set is huge...get the english ones right.
+// }
+// else
+// {
+// return isalnum( anyByte );
+// }
+}
+
+
+class TiXmlParsingData
+{
+ friend class TiXmlDocument;
+ public:
+ void Stamp( const char* now, TiXmlEncoding encoding );
+
+ const TiXmlCursor& Cursor() const { return cursor; }
+
+ private:
+ // Only used by the document!
+ TiXmlParsingData( const char* start, int _tabsize, int row, int col )
+ {
+ assert( start );
+ stamp = start;
+ tabsize = _tabsize;
+ cursor.row = row;
+ cursor.col = col;
+ }
+
+ TiXmlCursor cursor;
+ const char* stamp;
+ int tabsize;
+};
+
+
+void TiXmlParsingData::Stamp( const char* now, TiXmlEncoding encoding )
+{
+ assert( now );
+
+ // Do nothing if the tabsize is 0.
+ if ( tabsize < 1 )
+ {
+ return;
+ }
+
+ // Get the current row, column.
+ int row = cursor.row;
+ int col = cursor.col;
+ const char* p = stamp;
+ assert( p );
+
+ while ( p < now )
+ {
+ // Treat p as unsigned, so we have a happy compiler.
+ const unsigned char* pU = (const unsigned char*)p;
+
+ // Code contributed by Fletcher Dunn: (modified by lee)
+ switch (*pU) {
+ case 0:
+ // We *should* never get here, but in case we do, don't
+ // advance past the terminating null character, ever
+ return;
+
+ case '\r':
+ // bump down to the next line
+ ++row;
+ col = 0;
+ // Eat the character
+ ++p;
+
+ // Check for \r\n sequence, and treat this as a single character
+ if (*p == '\n') {
+ ++p;
+ }
+ break;
+
+ case '\n':
+ // bump down to the next line
+ ++row;
+ col = 0;
+
+ // Eat the character
+ ++p;
+
+ // Check for \n\r sequence, and treat this as a single
+ // character. (Yes, this bizarre thing does occur still
+ // on some arcane platforms...)
+ if (*p == '\r') {
+ ++p;
+ }
+ break;
+
+ case '\t':
+ // Eat the character
+ ++p;
+
+ // Skip to next tab stop
+ col = (col / tabsize + 1) * tabsize;
+ break;
+
+ case TIXML_UTF_LEAD_0:
+ if ( encoding == TIXML_ENCODING_UTF8 )
+ {
+ if ( *(p+1) && *(p+2) )
+ {
+ // In these cases, don't advance the column. These are
+ // 0-width spaces.
+ if ( *(pU+1)==TIXML_UTF_LEAD_1 && *(pU+2)==TIXML_UTF_LEAD_2 )
+ p += 3;
+ else if ( *(pU+1)==0xbfU && *(pU+2)==0xbeU )
+ p += 3;
+ else if ( *(pU+1)==0xbfU && *(pU+2)==0xbfU )
+ p += 3;
+ else
+ { p +=3; ++col; } // A normal character.
+ }
+ }
+ else
+ {
+ ++p;
+ ++col;
+ }
+ break;
+
+ default:
+ if ( encoding == TIXML_ENCODING_UTF8 )
+ {
+ // Eat the 1 to 4 byte utf8 character.
+ int step = TiXmlBase::utf8ByteTable[*((const unsigned char*)p)];
+ if ( step == 0 )
+ step = 1; // Error case from bad encoding, but handle gracefully.
+ p += step;
+
+ // Just advance one column, of course.
+ ++col;
+ }
+ else
+ {
+ ++p;
+ ++col;
+ }
+ break;
+ }
+ }
+ cursor.row = row;
+ cursor.col = col;
+ assert( cursor.row >= -1 );
+ assert( cursor.col >= -1 );
+ stamp = p;
+ assert( stamp );
+}
+
+
+const char* TiXmlBase::SkipWhiteSpace( const char* p, TiXmlEncoding encoding )
+{
+ if ( !p || !*p )
+ {
+ return 0;
+ }
+ if ( encoding == TIXML_ENCODING_UTF8 )
+ {
+ while ( *p )
+ {
+ const unsigned char* pU = (const unsigned char*)p;
+
+ // Skip the stupid Microsoft UTF-8 Byte order marks
+ if ( *(pU+0)==TIXML_UTF_LEAD_0
+ && *(pU+1)==TIXML_UTF_LEAD_1
+ && *(pU+2)==TIXML_UTF_LEAD_2 )
+ {
+ p += 3;
+ continue;
+ }
+ else if(*(pU+0)==TIXML_UTF_LEAD_0
+ && *(pU+1)==0xbfU
+ && *(pU+2)==0xbeU )
+ {
+ p += 3;
+ continue;
+ }
+ else if(*(pU+0)==TIXML_UTF_LEAD_0
+ && *(pU+1)==0xbfU
+ && *(pU+2)==0xbfU )
+ {
+ p += 3;
+ continue;
+ }
+
+ if ( IsWhiteSpace( *p ) ) // Still using old rules for white space.
+ ++p;
+ else
+ break;
+ }
+ }
+ else
+ {
+ while ( *p && IsWhiteSpace( *p ) )
+ ++p;
+ }
+
+ return p;
+}
+
+#ifdef TIXML_USE_STL
+/*static*/ bool TiXmlBase::StreamWhiteSpace( std::istream * in, TIXML_STRING * tag )
+{
+ for( ;; )
+ {
+ if ( !in->good() ) return false;
+
+ int c = in->peek();
+ // At this scope, we can't get to a document. So fail silently.
+ if ( !IsWhiteSpace( c ) || c <= 0 )
+ return true;
+
+ *tag += (char) in->get();
+ }
+}
+
+/*static*/ bool TiXmlBase::StreamTo( std::istream * in, int character, TIXML_STRING * tag )
+{
+ //assert( character > 0 && character < 128 ); // else it won't work in utf-8
+ while ( in->good() )
+ {
+ int c = in->peek();
+ if ( c == character )
+ return true;
+ if ( c <= 0 ) // Silent failure: can't get document at this scope
+ return false;
+
+ in->get();
+ *tag += (char) c;
+ }
+ return false;
+}
+#endif
+
+// One of TinyXML's more performance demanding functions. Try to keep the memory overhead down. The
+// "assign" optimization removes over 10% of the execution time.
+//
+const char* TiXmlBase::ReadName( const char* p, TIXML_STRING * name, TiXmlEncoding encoding )
+{
+ // Oddly, not supported on some comilers,
+ //name->clear();
+ // So use this:
+ *name = "";
+ assert( p );
+
+ // Names start with letters or underscores.
+ // Of course, in unicode, tinyxml has no idea what a letter *is*. The
+ // algorithm is generous.
+ //
+ // After that, they can be letters, underscores, numbers,
+ // hyphens, or colons. (Colons are valid ony for namespaces,
+ // but tinyxml can't tell namespaces from names.)
+ if ( p && *p
+ && ( IsAlpha( (unsigned char) *p, encoding ) || *p == '_' ) )
+ {
+ const char* start = p;
+ while( p && *p
+ && ( IsAlphaNum( (unsigned char ) *p, encoding )
+ || *p == '_'
+ || *p == '-'
+ || *p == '.'
+ || *p == ':' ) )
+ {
+ //(*name) += *p; // expensive
+ ++p;
+ }
+ if ( p-start > 0 ) {
+ name->assign( start, p-start );
+ }
+ return p;
+ }
+ return 0;
+}
+
+const char* TiXmlBase::GetEntity( const char* p, char* value, int* length, TiXmlEncoding encoding )
+{
+ // Presume an entity, and pull it out.
+ TIXML_STRING ent;
+ int i;
+ *length = 0;
+
+ if ( *(p+1) && *(p+1) == '#' && *(p+2) )
+ {
+ unsigned long ucs = 0;
+ ptrdiff_t delta = 0;
+ unsigned mult = 1;
+
+ if ( *(p+2) == 'x' )
+ {
+ // Hexadecimal.
+ if ( !*(p+3) ) return 0;
+
+ const char* q = p+3;
+ q = strchr( q, ';' );
+
+ if ( !q || !*q ) return 0;
+
+ delta = q-p;
+ --q;
+
+ while ( *q != 'x' )
+ {
+ if ( *q >= '0' && *q <= '9' )
+ ucs += mult * (*q - '0');
+ else if ( *q >= 'a' && *q <= 'f' )
+ ucs += mult * (*q - 'a' + 10);
+ else if ( *q >= 'A' && *q <= 'F' )
+ ucs += mult * (*q - 'A' + 10 );
+ else
+ return 0;
+ mult *= 16;
+ --q;
+ }
+ }
+ else
+ {
+ // Decimal.
+ if ( !*(p+2) ) return 0;
+
+ const char* q = p+2;
+ q = strchr( q, ';' );
+
+ if ( !q || !*q ) return 0;
+
+ delta = q-p;
+ --q;
+
+ while ( *q != '#' )
+ {
+ if ( *q >= '0' && *q <= '9' )
+ ucs += mult * (*q - '0');
+ else
+ return 0;
+ mult *= 10;
+ --q;
+ }
+ }
+ if ( encoding == TIXML_ENCODING_UTF8 )
+ {
+ // convert the UCS to UTF-8
+ ConvertUTF32ToUTF8( ucs, value, length );
+ }
+ else
+ {
+ *value = (char)ucs;
+ *length = 1;
+ }
+ return p + delta + 1;
+ }
+
+ // Now try to match it.
+ for( i=0; i<NUM_ENTITY; ++i )
+ {
+ if ( strncmp( entity[i].str, p, entity[i].strLength ) == 0 )
+ {
+ assert( strlen( entity[i].str ) == entity[i].strLength );
+ *value = entity[i].chr;
+ *length = 1;
+ return ( p + entity[i].strLength );
+ }
+ }
+
+ // So it wasn't an entity, its unrecognized, or something like that.
+ *value = *p; // Don't put back the last one, since we return it!
+ //*length = 1; // Leave unrecognized entities - this doesn't really work.
+ // Just writes strange XML.
+ return p+1;
+}
+
+
+bool TiXmlBase::StringEqual( const char* p,
+ const char* tag,
+ bool ignoreCase,
+ TiXmlEncoding encoding )
+{
+ assert( p );
+ assert( tag );
+ if ( !p || !*p )
+ {
+ assert( 0 );
+ return false;
+ }
+
+ const char* q = p;
+
+ if ( ignoreCase )
+ {
+ while ( *q && *tag && ToLower( *q, encoding ) == ToLower( *tag, encoding ) )
+ {
+ ++q;
+ ++tag;
+ }
+
+ if ( *tag == 0 )
+ return true;
+ }
+ else
+ {
+ while ( *q && *tag && *q == *tag )
+ {
+ ++q;
+ ++tag;
+ }
+
+ if ( *tag == 0 ) // Have we found the end of the tag, and everything equal?
+ return true;
+ }
+ return false;
+}
+
+const char* TiXmlBase::ReadText( const char* p,
+ TIXML_STRING * text,
+ bool trimWhiteSpace,
+ const char* endTag,
+ bool caseInsensitive,
+ TiXmlEncoding encoding )
+{
+ *text = "";
+ if ( !trimWhiteSpace // certain tags always keep whitespace
+ || !condenseWhiteSpace ) // if true, whitespace is always kept
+ {
+ // Keep all the white space.
+ while ( p && *p
+ && !StringEqual( p, endTag, caseInsensitive, encoding )
+ )
+ {
+ int len;
+ char cArr[4] = { 0, 0, 0, 0 };
+ p = GetChar( p, cArr, &len, encoding );
+ text->append( cArr, len );
+ }
+ }
+ else
+ {
+ bool whitespace = false;
+
+ // Remove leading white space:
+ p = SkipWhiteSpace( p, encoding );
+ while ( p && *p
+ && !StringEqual( p, endTag, caseInsensitive, encoding ) )
+ {
+ if ( *p == '\r' || *p == '\n' )
+ {
+ whitespace = true;
+ ++p;
+ }
+ else if ( IsWhiteSpace( *p ) )
+ {
+ whitespace = true;
+ ++p;
+ }
+ else
+ {
+ // If we've found whitespace, add it before the
+ // new character. Any whitespace just becomes a space.
+ if ( whitespace )
+ {
+ (*text) += ' ';
+ whitespace = false;
+ }
+ int len;
+ char cArr[4] = { 0, 0, 0, 0 };
+ p = GetChar( p, cArr, &len, encoding );
+ if ( len == 1 )
+ (*text) += cArr[0]; // more efficient
+ else
+ text->append( cArr, len );
+ }
+ }
+ }
+ if ( p && *p )
+ p += strlen( endTag );
+ return ( p && *p ) ? p : 0;
+}
+
+#ifdef TIXML_USE_STL
+
+void TiXmlDocument::StreamIn( std::istream * in, TIXML_STRING * tag )
+{
+ // The basic issue with a document is that we don't know what we're
+ // streaming. Read something presumed to be a tag (and hope), then
+ // identify it, and call the appropriate stream method on the tag.
+ //
+ // This "pre-streaming" will never read the closing ">" so the
+ // sub-tag can orient itself.
+
+ if ( !StreamTo( in, '<', tag ) )
+ {
+ SetError( TIXML_ERROR_PARSING_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN );
+ return;
+ }
+
+ while ( in->good() )
+ {
+ int tagIndex = (int) tag->length();
+ while ( in->good() && in->peek() != '>' )
+ {
+ int c = in->get();
+ if ( c <= 0 )
+ {
+ SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN );
+ break;
+ }
+ (*tag) += (char) c;
+ }
+
+ if ( in->good() )
+ {
+ // We now have something we presume to be a node of
+ // some sort. Identify it, and call the node to
+ // continue streaming.
+ TiXmlNode* node = Identify( tag->c_str() + tagIndex, TIXML_DEFAULT_ENCODING );
+
+ if ( node )
+ {
+ node->StreamIn( in, tag );
+ bool isElement = node->ToElement() != 0;
+ delete node;
+ node = 0;
+
+ // If this is the root element, we're done. Parsing will be
+ // done by the >> operator.
+ if ( isElement )
+ {
+ return;
+ }
+ }
+ else
+ {
+ SetError( TIXML_ERROR, 0, 0, TIXML_ENCODING_UNKNOWN );
+ return;
+ }
+ }
+ }
+ // We should have returned sooner.
+ SetError( TIXML_ERROR, 0, 0, TIXML_ENCODING_UNKNOWN );
+}
+
+#endif
+
+const char* TiXmlDocument::Parse( const char* p, TiXmlParsingData* prevData, TiXmlEncoding encoding )
+{
+ ClearError();
+
+ // Parse away, at the document level. Since a document
+ // contains nothing but other tags, most of what happens
+ // here is skipping white space.
+ if ( !p || !*p )
+ {
+ SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN );
+ return 0;
+ }
+
+ // Note that, for a document, this needs to come
+ // before the while space skip, so that parsing
+ // starts from the pointer we are given.
+ location.Clear();
+ if ( prevData )
+ {
+ location.row = prevData->cursor.row;
+ location.col = prevData->cursor.col;
+ }
+ else
+ {
+ location.row = 0;
+ location.col = 0;
+ }
+ TiXmlParsingData data( p, TabSize(), location.row, location.col );
+ location = data.Cursor();
+
+ if ( encoding == TIXML_ENCODING_UNKNOWN )
+ {
+ // Check for the Microsoft UTF-8 lead bytes.
+ const unsigned char* pU = (const unsigned char*)p;
+ if ( *(pU+0) && *(pU+0) == TIXML_UTF_LEAD_0
+ && *(pU+1) && *(pU+1) == TIXML_UTF_LEAD_1
+ && *(pU+2) && *(pU+2) == TIXML_UTF_LEAD_2 )
+ {
+ encoding = TIXML_ENCODING_UTF8;
+ useMicrosoftBOM = true;
+ }
+ }
+
+ p = SkipWhiteSpace( p, encoding );
+ if ( !p )
+ {
+ SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN );
+ return 0;
+ }
+
+ while ( p && *p )
+ {
+ TiXmlNode* node = Identify( p, encoding );
+ if ( node )
+ {
+ p = node->Parse( p, &data, encoding );
+ LinkEndChild( node );
+ }
+ else
+ {
+ break;
+ }
+
+ // Did we get encoding info?
+ if ( encoding == TIXML_ENCODING_UNKNOWN
+ && node->ToDeclaration() )
+ {
+ TiXmlDeclaration* dec = node->ToDeclaration();
+ const char* enc = dec->Encoding();
+ assert( enc );
+
+ if ( *enc == 0 )
+ encoding = TIXML_ENCODING_UTF8;
+ else if ( StringEqual( enc, "UTF-8", true, TIXML_ENCODING_UNKNOWN ) )
+ encoding = TIXML_ENCODING_UTF8;
+ else if ( StringEqual( enc, "UTF8", true, TIXML_ENCODING_UNKNOWN ) )
+ encoding = TIXML_ENCODING_UTF8; // incorrect, but be nice
+ else
+ encoding = TIXML_ENCODING_LEGACY;
+ }
+
+ p = SkipWhiteSpace( p, encoding );
+ }
+
+ // Was this empty?
+ if ( !firstChild ) {
+ SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, encoding );
+ return 0;
+ }
+
+ // All is well.
+ return p;
+}
+
+void TiXmlDocument::SetError( int err, const char* pError, TiXmlParsingData* data, TiXmlEncoding encoding )
+{
+ // The first error in a chain is more accurate - don't set again!
+ if ( error )
+ return;
+
+ assert( err > 0 && err < TIXML_ERROR_STRING_COUNT );
+ error = true;
+ errorId = err;
+ errorDesc = errorString[ errorId ];
+
+ errorLocation.Clear();
+ if ( pError && data )
+ {
+ data->Stamp( pError, encoding );
+ errorLocation = data->Cursor();
+ }
+}
+
+
+TiXmlNode* TiXmlNode::Identify( const char* p, TiXmlEncoding encoding )
+{
+ TiXmlNode* returnNode = 0;
+
+ p = SkipWhiteSpace( p, encoding );
+ if( !p || !*p || *p != '<' )
+ {
+ return 0;
+ }
+
+ p = SkipWhiteSpace( p, encoding );
+
+ if ( !p || !*p )
+ {
+ return 0;
+ }
+
+ // What is this thing?
+ // - Elements start with a letter or underscore, but xml is reserved.
+ // - Comments: <!--
+ // - Decleration: <?xml
+ // - Everthing else is unknown to tinyxml.
+ //
+
+ const char* xmlHeader = { "<?xml" };
+ const char* commentHeader = { "<!--" };
+ const char* dtdHeader = { "<!" };
+ const char* cdataHeader = { "<![CDATA[" };
+
+ if ( StringEqual( p, xmlHeader, true, encoding ) )
+ {
+ #ifdef DEBUG_PARSER
+ TIXML_LOG( "XML parsing Declaration\n" );
+ #endif
+ returnNode = new TiXmlDeclaration();
+ }
+ else if ( StringEqual( p, commentHeader, false, encoding ) )
+ {
+ #ifdef DEBUG_PARSER
+ TIXML_LOG( "XML parsing Comment\n" );
+ #endif
+ returnNode = new TiXmlComment();
+ }
+ else if ( StringEqual( p, cdataHeader, false, encoding ) )
+ {
+ #ifdef DEBUG_PARSER
+ TIXML_LOG( "XML parsing CDATA\n" );
+ #endif
+ TiXmlText* text = new TiXmlText( "" );
+ text->SetCDATA( true );
+ returnNode = text;
+ }
+ else if ( StringEqual( p, dtdHeader, false, encoding ) )
+ {
+ #ifdef DEBUG_PARSER
+ TIXML_LOG( "XML parsing Unknown(1)\n" );
+ #endif
+ returnNode = new TiXmlUnknown();
+ }
+ else if ( IsAlpha( *(p+1), encoding )
+ || *(p+1) == '_' )
+ {
+ #ifdef DEBUG_PARSER
+ TIXML_LOG( "XML parsing Element\n" );
+ #endif
+ returnNode = new TiXmlElement( "" );
+ }
+ else
+ {
+ #ifdef DEBUG_PARSER
+ TIXML_LOG( "XML parsing Unknown(2)\n" );
+ #endif
+ returnNode = new TiXmlUnknown();
+ }
+
+ if ( returnNode )
+ {
+ // Set the parent, so it can report errors
+ returnNode->parent = this;
+ }
+ return returnNode;
+}
+
+#ifdef TIXML_USE_STL
+
+void TiXmlElement::StreamIn (std::istream * in, TIXML_STRING * tag)
+{
+ // We're called with some amount of pre-parsing. That is, some of "this"
+ // element is in "tag". Go ahead and stream to the closing ">"
+ while( in->good() )
+ {
+ int c = in->get();
+ if ( c <= 0 )
+ {
+ TiXmlDocument* document = GetDocument();
+ if ( document )
+ document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN );
+ return;
+ }
+ (*tag) += (char) c ;
+
+ if ( c == '>' )
+ break;
+ }
+
+ if ( tag->length() < 3 ) return;
+
+ // Okay...if we are a "/>" tag, then we're done. We've read a complete tag.
+ // If not, identify and stream.
+
+ if ( tag->at( tag->length() - 1 ) == '>'
+ && tag->at( tag->length() - 2 ) == '/' )
+ {
+ // All good!
+ return;
+ }
+ else if ( tag->at( tag->length() - 1 ) == '>' )
+ {
+ // There is more. Could be:
+ // text
+ // cdata text (which looks like another node)
+ // closing tag
+ // another node.
+ for ( ;; )
+ {
+ StreamWhiteSpace( in, tag );
+
+ // Do we have text?
+ if ( in->good() && in->peek() != '<' )
+ {
+ // Yep, text.
+ TiXmlText text( "" );
+ text.StreamIn( in, tag );
+
+ // What follows text is a closing tag or another node.
+ // Go around again and figure it out.
+ continue;
+ }
+
+ // We now have either a closing tag...or another node.
+ // We should be at a "<", regardless.
+ if ( !in->good() ) return;
+ assert( in->peek() == '<' );
+ int tagIndex = (int) tag->length();
+
+ bool closingTag = false;
+ bool firstCharFound = false;
+
+ for( ;; )
+ {
+ if ( !in->good() )
+ return;
+
+ int c = in->peek();
+ if ( c <= 0 )
+ {
+ TiXmlDocument* document = GetDocument();
+ if ( document )
+ document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN );
+ return;
+ }
+
+ if ( c == '>' )
+ break;
+
+ *tag += (char) c;
+ in->get();
+
+ // Early out if we find the CDATA id.
+ if ( c == '[' && tag->size() >= 9 )
+ {
+ size_t len = tag->size();
+ const char* start = tag->c_str() + len - 9;
+ if ( strcmp( start, "<![CDATA[" ) == 0 ) {
+ assert( !closingTag );
+ break;
+ }
+ }
+
+ if ( !firstCharFound && c != '<' && !IsWhiteSpace( c ) )
+ {
+ firstCharFound = true;
+ if ( c == '/' )
+ closingTag = true;
+ }
+ }
+ // If it was a closing tag, then read in the closing '>' to clean up the input stream.
+ // If it was not, the streaming will be done by the tag.
+ if ( closingTag )
+ {
+ if ( !in->good() )
+ return;
+
+ int c = in->get();
+ if ( c <= 0 )
+ {
+ TiXmlDocument* document = GetDocument();
+ if ( document )
+ document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN );
+ return;
+ }
+ assert( c == '>' );
+ *tag += (char) c;
+
+ // We are done, once we've found our closing tag.
+ return;
+ }
+ else
+ {
+ // If not a closing tag, id it, and stream.
+ const char* tagloc = tag->c_str() + tagIndex;
+ TiXmlNode* node = Identify( tagloc, TIXML_DEFAULT_ENCODING );
+ if ( !node )
+ return;
+ node->StreamIn( in, tag );
+ delete node;
+ node = 0;
+
+ // No return: go around from the beginning: text, closing tag, or node.
+ }
+ }
+ }
+}
+#endif
+
+const char* TiXmlElement::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding )
+{
+ p = SkipWhiteSpace( p, encoding );
+ TiXmlDocument* document = GetDocument();
+
+ if ( !p || !*p )
+ {
+ if ( document ) document->SetError( TIXML_ERROR_PARSING_ELEMENT, 0, 0, encoding );
+ return 0;
+ }
+
+ if ( data )
+ {
+ data->Stamp( p, encoding );
+ location = data->Cursor();
+ }
+
+ if ( *p != '<' )
+ {
+ if ( document ) document->SetError( TIXML_ERROR_PARSING_ELEMENT, p, data, encoding );
+ return 0;
+ }
+
+ p = SkipWhiteSpace( p+1, encoding );
+
+ // Read the name.
+ const char* pErr = p;
+
+ p = ReadName( p, &value, encoding );
+ if ( !p || !*p )
+ {
+ if ( document ) document->SetError( TIXML_ERROR_FAILED_TO_READ_ELEMENT_NAME, pErr, data, encoding );
+ return 0;
+ }
+
+ TIXML_STRING endTag ("</");
+ endTag += value;
+
+ // Check for and read attributes. Also look for an empty
+ // tag or an end tag.
+ while ( p && *p )
+ {
+ pErr = p;
+ p = SkipWhiteSpace( p, encoding );
+ if ( !p || !*p )
+ {
+ if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, pErr, data, encoding );
+ return 0;
+ }
+ if ( *p == '/' )
+ {
+ ++p;
+ // Empty tag.
+ if ( *p != '>' )
+ {
+ if ( document ) document->SetError( TIXML_ERROR_PARSING_EMPTY, p, data, encoding );
+ return 0;
+ }
+ return (p+1);
+ }
+ else if ( *p == '>' )
+ {
+ // Done with attributes (if there were any.)
+ // Read the value -- which can include other
+ // elements -- read the end tag, and return.
+ ++p;
+ p = ReadValue( p, data, encoding ); // Note this is an Element method, and will set the error if one happens.
+ if ( !p || !*p ) {
+ // We were looking for the end tag, but found nothing.
+ // Fix for [ 1663758 ] Failure to report error on bad XML
+ if ( document ) document->SetError( TIXML_ERROR_READING_END_TAG, p, data, encoding );
+ return 0;
+ }
+
+ // We should find the end tag now
+ // note that:
+ // </foo > and
+ // </foo>
+ // are both valid end tags.
+ if ( StringEqual( p, endTag.c_str(), false, encoding ) )
+ {
+ p += endTag.length();
+ p = SkipWhiteSpace( p, encoding );
+ if ( p && *p && *p == '>' ) {
+ ++p;
+ return p;
+ }
+ if ( document ) document->SetError( TIXML_ERROR_READING_END_TAG, p, data, encoding );
+ return 0;
+ }
+ else
+ {
+ if ( document ) document->SetError( TIXML_ERROR_READING_END_TAG, p, data, encoding );
+ return 0;
+ }
+ }
+ else
+ {
+ // Try to read an attribute:
+ TiXmlAttribute* attrib = new TiXmlAttribute();
+ if ( !attrib )
+ {
+ return 0;
+ }
+
+ attrib->SetDocument( document );
+ pErr = p;
+ p = attrib->Parse( p, data, encoding );
+
+ if ( !p || !*p )
+ {
+ if ( document ) document->SetError( TIXML_ERROR_PARSING_ELEMENT, pErr, data, encoding );
+ delete attrib;
+ return 0;
+ }
+
+ // Handle the strange case of double attributes:
+ #ifdef TIXML_USE_STL
+ TiXmlAttribute* node = attributeSet.Find( attrib->NameTStr() );
+ #else
+ TiXmlAttribute* node = attributeSet.Find( attrib->Name() );
+ #endif
+ if ( node )
+ {
+ if ( document ) document->SetError( TIXML_ERROR_PARSING_ELEMENT, pErr, data, encoding );
+ delete attrib;
+ return 0;
+ }
+
+ attributeSet.Add( attrib );
+ }
+ }
+ return p;
+}
+
+
+const char* TiXmlElement::ReadValue( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding )
+{
+ TiXmlDocument* document = GetDocument();
+
+ // Read in text and elements in any order.
+ const char* pWithWhiteSpace = p;
+ p = SkipWhiteSpace( p, encoding );
+
+ while ( p && *p )
+ {
+ if ( *p != '<' )
+ {
+ // Take what we have, make a text element.
+ TiXmlText* textNode = new TiXmlText( "" );
+
+ if ( !textNode )
+ {
+ return 0;
+ }
+
+ if ( TiXmlBase::IsWhiteSpaceCondensed() )
+ {
+ p = textNode->Parse( p, data, encoding );
+ }
+ else
+ {
+ // Special case: we want to keep the white space
+ // so that leading spaces aren't removed.
+ p = textNode->Parse( pWithWhiteSpace, data, encoding );
+ }
+
+ if ( !textNode->Blank() )
+ LinkEndChild( textNode );
+ else
+ delete textNode;
+ }
+ else
+ {
+ // We hit a '<'
+ // Have we hit a new element or an end tag? This could also be
+ // a TiXmlText in the "CDATA" style.
+ if ( StringEqual( p, "</", false, encoding ) )
+ {
+ return p;
+ }
+ else
+ {
+ TiXmlNode* node = Identify( p, encoding );
+ if ( node )
+ {
+ p = node->Parse( p, data, encoding );
+ LinkEndChild( node );
+ }
+ else
+ {
+ return 0;
+ }
+ }
+ }
+ pWithWhiteSpace = p;
+ p = SkipWhiteSpace( p, encoding );
+ }
+
+ if ( !p )
+ {
+ if ( document ) document->SetError( TIXML_ERROR_READING_ELEMENT_VALUE, 0, 0, encoding );
+ }
+ return p;
+}
+
+
+#ifdef TIXML_USE_STL
+void TiXmlUnknown::StreamIn( std::istream * in, TIXML_STRING * tag )
+{
+ while ( in->good() )
+ {
+ int c = in->get();
+ if ( c <= 0 )
+ {
+ TiXmlDocument* document = GetDocument();
+ if ( document )
+ document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN );
+ return;
+ }
+ (*tag) += (char) c;
+
+ if ( c == '>' )
+ {
+ // All is well.
+ return;
+ }
+ }
+}
+#endif
+
+
+const char* TiXmlUnknown::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding )
+{
+ TiXmlDocument* document = GetDocument();
+ p = SkipWhiteSpace( p, encoding );
+
+ if ( data )
+ {
+ data->Stamp( p, encoding );
+ location = data->Cursor();
+ }
+ if ( !p || !*p || *p != '<' )
+ {
+ if ( document ) document->SetError( TIXML_ERROR_PARSING_UNKNOWN, p, data, encoding );
+ return 0;
+ }
+ ++p;
+ value = "";
+
+ while ( p && *p && *p != '>' )
+ {
+ value += *p;
+ ++p;
+ }
+
+ if ( !p )
+ {
+ if ( document )
+ document->SetError( TIXML_ERROR_PARSING_UNKNOWN, 0, 0, encoding );
+ }
+ if ( p && *p == '>' )
+ return p+1;
+ return p;
+}
+
+#ifdef TIXML_USE_STL
+void TiXmlComment::StreamIn( std::istream * in, TIXML_STRING * tag )
+{
+ while ( in->good() )
+ {
+ int c = in->get();
+ if ( c <= 0 )
+ {
+ TiXmlDocument* document = GetDocument();
+ if ( document )
+ document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN );
+ return;
+ }
+
+ (*tag) += (char) c;
+
+ if ( c == '>'
+ && tag->at( tag->length() - 2 ) == '-'
+ && tag->at( tag->length() - 3 ) == '-' )
+ {
+ // All is well.
+ return;
+ }
+ }
+}
+#endif
+
+
+const char* TiXmlComment::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding )
+{
+ TiXmlDocument* document = GetDocument();
+ value = "";
+
+ p = SkipWhiteSpace( p, encoding );
+
+ if ( data )
+ {
+ data->Stamp( p, encoding );
+ location = data->Cursor();
+ }
+ const char* startTag = "<!--";
+ const char* endTag = "-->";
+
+ if ( !StringEqual( p, startTag, false, encoding ) )
+ {
+ if ( document )
+ document->SetError( TIXML_ERROR_PARSING_COMMENT, p, data, encoding );
+ return 0;
+ }
+ p += strlen( startTag );
+
+ // [ 1475201 ] TinyXML parses entities in comments
+ // Oops - ReadText doesn't work, because we don't want to parse the entities.
+ // p = ReadText( p, &value, false, endTag, false, encoding );
+ //
+ // from the XML spec:
+ /*
+ [Definition: Comments may appear anywhere in a document outside other markup; in addition,
+ they may appear within the document type declaration at places allowed by the grammar.
+ They are not part of the document's character data; an XML processor MAY, but need not,
+ make it possible for an application to retrieve the text of comments. For compatibility,
+ the string "--" (double-hyphen) MUST NOT occur within comments.] Parameter entity
+ references MUST NOT be recognized within comments.
+
+ An example of a comment:
+
+ <!-- declarations for <head> & <body> -->
+ */
+
+ value = "";
+ // Keep all the white space.
+ while ( p && *p && !StringEqual( p, endTag, false, encoding ) )
+ {
+ value.append( p, 1 );
+ ++p;
+ }
+ if ( p && *p )
+ p += strlen( endTag );
+
+ return p;
+}
+
+
+const char* TiXmlAttribute::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding )
+{
+ p = SkipWhiteSpace( p, encoding );
+ if ( !p || !*p ) return 0;
+
+ if ( data )
+ {
+ data->Stamp( p, encoding );
+ location = data->Cursor();
+ }
+ // Read the name, the '=' and the value.
+ const char* pErr = p;
+ p = ReadName( p, &name, encoding );
+ if ( !p || !*p )
+ {
+ if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, pErr, data, encoding );
+ return 0;
+ }
+ p = SkipWhiteSpace( p, encoding );
+ if ( !p || !*p || *p != '=' )
+ {
+ if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding );
+ return 0;
+ }
+
+ ++p; // skip '='
+ p = SkipWhiteSpace( p, encoding );
+ if ( !p || !*p )
+ {
+ if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding );
+ return 0;
+ }
+
+ const char* end;
+ const char SINGLE_QUOTE = '\'';
+ const char DOUBLE_QUOTE = '\"';
+
+ if ( *p == SINGLE_QUOTE )
+ {
+ ++p;
+ end = "\'"; // single quote in string
+ p = ReadText( p, &value, false, end, false, encoding );
+ }
+ else if ( *p == DOUBLE_QUOTE )
+ {
+ ++p;
+ end = "\""; // double quote in string
+ p = ReadText( p, &value, false, end, false, encoding );
+ }
+ else
+ {
+ // All attribute values should be in single or double quotes.
+ // But this is such a common error that the parser will try
+ // its best, even without them.
+ value = "";
+ while ( p && *p // existence
+ && !IsWhiteSpace( *p ) // whitespace
+ && *p != '/' && *p != '>' ) // tag end
+ {
+ if ( *p == SINGLE_QUOTE || *p == DOUBLE_QUOTE ) {
+ // [ 1451649 ] Attribute values with trailing quotes not handled correctly
+ // We did not have an opening quote but seem to have a
+ // closing one. Give up and throw an error.
+ if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding );
+ return 0;
+ }
+ value += *p;
+ ++p;
+ }
+ }
+ return p;
+}
+
+#ifdef TIXML_USE_STL
+void TiXmlText::StreamIn( std::istream * in, TIXML_STRING * tag )
+{
+ while ( in->good() )
+ {
+ int c = in->peek();
+ if ( !cdata && (c == '<' ) )
+ {
+ return;
+ }
+ if ( c <= 0 )
+ {
+ TiXmlDocument* document = GetDocument();
+ if ( document )
+ document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN );
+ return;
+ }
+
+ (*tag) += (char) c;
+ in->get(); // "commits" the peek made above
+
+ if ( cdata && c == '>' && tag->size() >= 3 ) {
+ size_t len = tag->size();
+ if ( (*tag)[len-2] == ']' && (*tag)[len-3] == ']' ) {
+ // terminator of cdata.
+ return;
+ }
+ }
+ }
+}
+#endif
+
+const char* TiXmlText::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding )
+{
+ value = "";
+ TiXmlDocument* document = GetDocument();
+
+ if ( data )
+ {
+ data->Stamp( p, encoding );
+ location = data->Cursor();
+ }
+
+ const char* const startTag = "<![CDATA[";
+ const char* const endTag = "]]>";
+
+ if ( cdata || StringEqual( p, startTag, false, encoding ) )
+ {
+ cdata = true;
+
+ if ( !StringEqual( p, startTag, false, encoding ) )
+ {
+ if ( document )
+ document->SetError( TIXML_ERROR_PARSING_CDATA, p, data, encoding );
+ return 0;
+ }
+ p += strlen( startTag );
+
+ // Keep all the white space, ignore the encoding, etc.
+ while ( p && *p
+ && !StringEqual( p, endTag, false, encoding )
+ )
+ {
+ value += *p;
+ ++p;
+ }
+
+ TIXML_STRING dummy;
+ p = ReadText( p, &dummy, false, endTag, false, encoding );
+ return p;
+ }
+ else
+ {
+ bool ignoreWhite = true;
+
+ const char* end = "<";
+ p = ReadText( p, &value, ignoreWhite, end, false, encoding );
+ if ( p && *p )
+ return p-1; // don't truncate the '<'
+ return 0;
+ }
+}
+
+#ifdef TIXML_USE_STL
+void TiXmlDeclaration::StreamIn( std::istream * in, TIXML_STRING * tag )
+{
+ while ( in->good() )
+ {
+ int c = in->get();
+ if ( c <= 0 )
+ {
+ TiXmlDocument* document = GetDocument();
+ if ( document )
+ document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN );
+ return;
+ }
+ (*tag) += (char) c;
+
+ if ( c == '>' )
+ {
+ // All is well.
+ return;
+ }
+ }
+}
+#endif
+
+const char* TiXmlDeclaration::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding _encoding )
+{
+ p = SkipWhiteSpace( p, _encoding );
+ // Find the beginning, find the end, and look for
+ // the stuff in-between.
+ TiXmlDocument* document = GetDocument();
+ if ( !p || !*p || !StringEqual( p, "<?xml", true, _encoding ) )
+ {
+ if ( document ) document->SetError( TIXML_ERROR_PARSING_DECLARATION, 0, 0, _encoding );
+ return 0;
+ }
+ if ( data )
+ {
+ data->Stamp( p, _encoding );
+ location = data->Cursor();
+ }
+ p += 5;
+
+ version = "";
+ encoding = "";
+ standalone = "";
+
+ while ( p && *p )
+ {
+ if ( *p == '>' )
+ {
+ ++p;
+ return p;
+ }
+
+ p = SkipWhiteSpace( p, _encoding );
+ if ( StringEqual( p, "version", true, _encoding ) )
+ {
+ TiXmlAttribute attrib;
+ p = attrib.Parse( p, data, _encoding );
+ version = attrib.Value();
+ }
+ else if ( StringEqual( p, "encoding", true, _encoding ) )
+ {
+ TiXmlAttribute attrib;
+ p = attrib.Parse( p, data, _encoding );
+ encoding = attrib.Value();
+ }
+ else if ( StringEqual( p, "standalone", true, _encoding ) )
+ {
+ TiXmlAttribute attrib;
+ p = attrib.Parse( p, data, _encoding );
+ standalone = attrib.Value();
+ }
+ else
+ {
+ // Read over whatever it is.
+ while( p && *p && *p != '>' && !IsWhiteSpace( *p ) )
+ ++p;
+ }
+ }
+ return 0;
+}
+
+bool TiXmlText::Blank() const
+{
+ for ( unsigned i=0; i<value.length(); i++ )
+ if ( !IsWhiteSpace( value[i] ) )
+ return false;
+ return true;
+}
+
diff --git a/mmc_updater/depends/win32cpp/controls.h b/mmc_updater/depends/win32cpp/controls.h
new file mode 100644
index 00000000..a15c8b5f
--- /dev/null
+++ b/mmc_updater/depends/win32cpp/controls.h
@@ -0,0 +1,1074 @@
+// Win32++ Version 7.2
+// Released: 5th AUgust 2011
+//
+// David Nash
+// email: dnash@bigpond.net.au
+// url: https://sourceforge.net/projects/win32-framework
+//
+//
+// Copyright (c) 2005-2011 David Nash
+//
+// Permission is hereby granted, free of charge, to
+// any person obtaining a copy of this software and
+// associated documentation files (the "Software"),
+// to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify,
+// merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom
+// the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice
+// shall be included in all copies or substantial portions
+// of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
+// OR OTHER DEALINGS IN THE SOFTWARE.
+//
+////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////
+// controls.h
+// Declaration of the following classes:
+// CAnimation, CComboBox, CComboBoxEx, CProgressBar,
+// CScrollBar, CSlider, CSpinButton
+
+
+#ifndef _WIN32XX_CONTROLS_H_
+#define _WIN32XX_CONTROLS_H_
+
+#include "wincore.h"
+
+namespace Win32xx
+{
+ class CAnimation : public CWnd
+ {
+ public:
+ CAnimation() {}
+ virtual ~CAnimation() {}
+
+ BOOL Close() const;
+ BOOL Open(LPTSTR lpszName) const;
+ BOOL Play(UINT wFrom, UINT wTo, UINT cRepeat) const;
+ BOOL Seek(UINT wFrame) const;
+ BOOL Stop() const;
+
+ protected:
+ // Overridables
+ virtual void PreRegisterClass(WNDCLASS &wc) { wc.lpszClassName = ANIMATE_CLASS; }
+ };
+
+
+ class CComboBox : public CWnd
+ {
+ public:
+ CComboBox() {}
+ virtual ~CComboBox() {}
+
+ int AddString(LPCTSTR lpszString) const;
+ void Clear() const;
+ void Copy() const;
+ void Cut() const;
+ int DeleteString(int nIndex) const;
+ int Dir(UINT attr, LPCTSTR lpszWildCard ) const;
+ int FindString(int nIndexStart, LPCTSTR lpszString) const;
+ int FindStringExact(int nIndexStart, LPCTSTR lpszString) const;
+ int GetCount() const;
+ int GetCurSel() const;
+ CRect GetDroppedControlRect() const;
+ BOOL GetDroppedState() const;
+ int GetDroppedWidth() const;
+ DWORD GetEditSel() const;
+ BOOL GetExtendedUI() const;
+ int GetHorizontalExtent() const;
+ DWORD GetItemData(int nIndex) const;
+ int GetItemHeight(int nIndex) const;
+ int GetLBText(int nIndex, LPTSTR lpszText) const;
+ int GetLBTextLen(int nIndex) const;
+ LCID GetLocale() const;
+ int GetTopIndex() const;
+ int InitStorage(int nItems, int nBytes) const;
+ int InsertString(int nIndex, LPCTSTR lpszString) const;
+ void LimitText(int nMaxChars) const;
+ void Paste() const;
+ void ResetContent() const;
+ int SelectString(int nStartAfter, LPCTSTR lpszString) const;
+ int SetCurSel(int nIndex) const;
+ int SetDroppedWidth(int nWidth) const;
+ BOOL SetEditSel(int nStartChar, int nEndChar) const;
+ int SetExtendedUI(BOOL bExtended = TRUE) const;
+ void SetHorizontalExtent(UINT nExtent ) const;
+ int SetItemData(int nIndex, DWORD dwItemData) const;
+ int SetItemHeight(int nIndex, UINT cyItemHeight) const;
+ LCID SetLocale( LCID NewLocale ) const;
+ int SetTopIndex(int nIndex) const;
+ void ShowDropDown(BOOL bShow = TRUE) const;
+
+ protected:
+ // Overridables
+ virtual void PreRegisterClass(WNDCLASS &wc) { wc.lpszClassName = _T("ComboBox"); }
+ };
+
+
+ class CComboBoxEx : public CWnd
+ {
+ public:
+ CComboBoxEx() {}
+ virtual ~CComboBoxEx() {}
+
+ int DeleteItem(int nIndex ) const;
+ CWnd* GetComboBoxCtrl() const;
+ CWnd* GetEditCtrl() const;
+ DWORD GetExtendedStyle() const;
+ HIMAGELIST GetImageList() const;
+ BOOL GetItem(COMBOBOXEXITEM* pCBItem) const;
+ BOOL HasEditChanged () const;
+ int InsertItem(COMBOBOXEXITEM* lpcCBItem) const;
+ DWORD SetExtendedStyle(DWORD dwExMask, DWORD dwExStyles ) const;
+ HIMAGELIST SetImageList(HIMAGELIST himl) const;
+ BOOL SetItem(PCOMBOBOXEXITEM lpcCBItem) const;
+
+ protected:
+ // Overridables
+ virtual void PreRegisterClass(WNDCLASS &wc) { wc.lpszClassName = WC_COMBOBOXEX; }
+ };
+
+
+ class CProgressBar : public CWnd
+ {
+ public:
+ CProgressBar() {}
+ virtual ~CProgressBar() {}
+
+ int GetPos() const;
+ int GetRange(BOOL fWhichLimit, PPBRANGE ppBRange) const;
+ int OffsetPos(int nIncrement) const;
+ int SetPos(int nNewPos) const;
+ int SetRange(short nMinRange, short nMaxRange) const;
+ int SetStep(int nStepInc) const;
+ int StepIt() const;
+
+ protected:
+ // Overridables
+ virtual void PreRegisterClass(WNDCLASS &wc) { wc.lpszClassName = PROGRESS_CLASS; }
+ };
+
+
+ class CScrollBar : public CWnd
+ {
+ public:
+ CScrollBar() {}
+ virtual ~CScrollBar() {}
+
+ BOOL EnableScrollBar( UINT nArrowFlags = ESB_ENABLE_BOTH ) const;
+ BOOL GetScrollInfo(LPSCROLLINFO lpsi) const;
+ int GetScrollPos() const;
+ BOOL GetScrollRange(LPINT lpMinPos, LPINT lpMaxPos ) const;
+ BOOL SetScrollInfo(LPSCROLLINFO lpsi, BOOL bRedraw = TRUE ) const;
+ int SetScrollPos(int nPos, BOOL bRedraw) const;
+ BOOL SetScrollRange( int nMinPos, int nMaxPos, BOOL bRedraw = TRUE ) const;
+ BOOL ShowScrollBar(BOOL bShow) const;
+
+ protected:
+ // Overridables
+ virtual void PreRegisterClass(WNDCLASS &wc) { wc.lpszClassName = _T("SCROLLBAR"); ; }
+ };
+
+
+ class CSlider : public CWnd
+ {
+ public:
+ CSlider() {}
+ virtual ~CSlider() {}
+
+ void ClearSel() const;
+ void ClearTics(BOOL bRedraw = FALSE ) const;
+ CWnd* GetBuddy(BOOL fLocation = TRUE ) const;
+ CRect GetChannelRect() const;
+ int GetLineSize() const;
+ int GetNumTics() const;
+ int GetPageSize() const;
+ int GetPos() const;
+ int GetRangeMax() const;
+ int GetRangeMin() const;
+ int GetSelEnd() const;
+ int GetSelStart() const;
+ int GetThumbLength() const;
+ CRect GetThumbRect() const;
+ int GetTic(int nTic ) const;
+ int GetTicPos(int nTic) const;
+ CWnd* GetToolTips() const;
+ CWnd* SetBuddy(CWnd* pBuddy, BOOL fLocation = TRUE ) const;
+ int SetLineSize(int nSize) const;
+ int SetPageSize(int nSize) const;
+ void SetPos(int nPos, BOOL bRedraw = FALSE) const;
+ void SetRangeMax(int nMax, BOOL bRedraw = FALSE) const;
+ void SetRangeMin(int nMax, BOOL bRedraw = FALSE) const;
+ void SetSelection(int nMin, int nMax, BOOL bRedraw = FALSE) const;
+ BOOL SetTic(int nTic) const;
+ void SetTicFreq(int nFreq) const;
+ int SetTipSide(int nLocation) const;
+ void SetToolTips(CWnd* pToolTip) const;
+
+ protected:
+ // Overridables
+ virtual void PreRegisterClass(WNDCLASS &wc) { wc.lpszClassName = TRACKBAR_CLASS; }
+ };
+
+
+ // Also known as an Up/Down control
+ class CSpinButton : public CWnd
+ {
+ public:
+ CSpinButton() {}
+ virtual ~CSpinButton() {}
+
+ int GetAccel(int cAccels, LPUDACCEL paAccels) const;
+ int GetBase() const;
+ CWnd* GetBuddy() const;
+ int GetPos() const;
+ DWORD GetRange() const;
+ BOOL SetAccel(int cAccels, LPUDACCEL paAccels) const;
+ int SetBase(int nBase) const;
+ CWnd* SetBuddy(CWnd* hwndBuddy) const;
+ int SetPos(int nPos) const;
+ void SetRange(int nLower, int nUpper) const;
+
+ protected:
+ // Overridables
+ virtual void PreCreate(CREATESTRUCT &cs);
+ virtual void PreRegisterClass(WNDCLASS &wc);
+ };
+
+} // namespace Win32xx
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+namespace Win32xx
+{
+
+ ////////////////////////////////////////
+ // Definitions for the CAnimation class
+ //
+ inline BOOL CAnimation::Close() const
+ // Closes an AVI clip.
+ {
+ assert(IsWindow());
+ return Animate_Close(m_hWnd);
+ }
+
+ inline BOOL CAnimation::Open(LPTSTR lpszName) const
+ // Opens an AVI clip and displays its first frame in an animation control.
+ {
+ assert(IsWindow());
+ return Animate_Open(m_hWnd, lpszName);
+ }
+
+ inline BOOL CAnimation::Play(UINT wFrom, UINT wTo, UINT cRepeat) const
+ // Plays an AVI clip in an animation control. The control plays the clip
+ // in the background while the thread continues executing.
+ {
+ assert(IsWindow());
+ return Animate_Play(m_hWnd, wFrom, wTo, cRepeat);
+ }
+
+ inline BOOL CAnimation::Seek(UINT wFrame) const
+ // Directs an animation control to display a particular frame of an AVI clip.
+ // The control displays the clip in the background while the thread continues executing.
+ {
+ assert(IsWindow());
+ return Animate_Seek(m_hWnd, wFrame);
+ }
+
+ inline BOOL CAnimation::Stop() const
+ // Stops playing an AVI clip in an animation control.
+ {
+ assert(IsWindow());
+ return Animate_Stop(m_hWnd);
+ }
+
+
+ ////////////////////////////////////////
+ // Definitions for the CComboBox class
+ //
+ inline int CComboBox::AddString(LPCTSTR lpszString) const
+ // Adds a string to the list box of a combo box. If the combo box does not
+ // have the CBS_SORT style, the string is added to the end of the list.
+ // Otherwise, the string is inserted into the list, and the list is sorted.
+ {
+ assert(IsWindow());
+ return (int)SendMessage(CB_ADDSTRING, 0, (LPARAM)lpszString);
+ }
+
+ inline void CComboBox::Clear() const
+ // Deletes the current selection, if any, from the combo box's edit control.
+ {
+ assert(IsWindow());
+ SendMessage(WM_CLEAR, 0, 0);
+ }
+
+ inline void CComboBox::Copy() const
+ // Copies the current selection to the clipboard in CF_TEXT format.
+ {
+ assert(IsWindow());
+ SendMessage(WM_COPY, 0, 0);
+ }
+
+ inline void CComboBox::Cut() const
+ // Deletes the current selection, if any, in the edit control and copies
+ // the deleted text to the clipboard in CF_TEXT format.
+ {
+ assert(IsWindow());
+ SendMessage(WM_CUT, 0, 0);
+ }
+
+ inline int CComboBox::DeleteString(int nIndex) const
+ // Deletes a string in the list box of a combo box.
+ {
+ assert(IsWindow());
+ return (int)SendMessage(CB_DELETESTRING, (WPARAM)nIndex, 0);
+ }
+
+ inline int CComboBox::Dir(UINT attr, LPCTSTR lpszWildCard ) const
+ // Adds the names of directories and files that match a specified string
+ // and set of file attributes.
+ {
+ assert(IsWindow());
+ return (int)SendMessage(CB_DIR, (WPARAM)attr, (LPARAM)lpszWildCard);
+ }
+
+ inline int CComboBox::FindString(int nIndexStart, LPCTSTR lpszString) const
+ // Search the list box of a combo box for an item beginning with the
+ // characters in a specified string.
+ {
+ assert(IsWindow());
+ return (int)SendMessage(CB_FINDSTRING, (WPARAM)nIndexStart, (LPARAM)lpszString);
+ }
+
+ inline int CComboBox::FindStringExact(int nIndexStart, LPCTSTR lpszString) const
+ // Find the first list box string in a combo box that matches the string specified in lpszString.
+ {
+ assert(IsWindow());
+ return (int)SendMessage(CB_FINDSTRINGEXACT, (WPARAM)nIndexStart, (LPARAM)lpszString);
+ }
+
+ inline int CComboBox::GetCount() const
+ // Retrieves the number of items in the list box of the combo box.
+ {
+ assert(IsWindow());
+ return (int)SendMessage(CB_GETCOUNT, 0,0);
+ }
+
+ inline int CComboBox::GetCurSel() const
+ // Retrieves the index of the currently selected item, if any, in the list box of the combo box.
+ {
+ assert(IsWindow());
+ return (int)SendMessage(CB_GETCURSEL, 0,0);
+ }
+
+ inline CRect CComboBox::GetDroppedControlRect() const
+ // Retrieves the screen coordinates of the combo box in its dropped-down state.
+ {
+ assert(IsWindow());
+ CRect rc;
+ SendMessage(CB_GETDROPPEDCONTROLRECT, 0, (LPARAM)&rc);
+ return rc;
+ }
+
+ inline BOOL CComboBox::GetDroppedState() const
+ // Determines whether the list box of the combo box is dropped down.
+ {
+ assert(IsWindow());
+ return (BOOL)SendMessage(CB_GETDROPPEDSTATE, 0, 0);
+ }
+
+ inline int CComboBox::GetDroppedWidth() const
+ // Retrieves the minimum allowable width, in pixels, of the list box of the combo box
+ // with the CBS_DROPDOWN or CBS_DROPDOWNLIST style.
+ {
+ assert(IsWindow());
+ return (int)SendMessage(CB_GETDROPPEDWIDTH, 0, 0);
+ }
+
+ inline DWORD CComboBox::GetEditSel() const
+ // Gets the starting and ending character positions of the current selection
+ // in the edit control of the combo box.
+ {
+ assert(IsWindow());
+ return (int)SendMessage(CB_GETEDITSEL, 0, 0);
+ }
+
+ inline BOOL CComboBox::GetExtendedUI() const
+ // Determines whether the combo box has the default user interface or the extended user interface.
+ {
+ assert(IsWindow());
+ return (BOOL)SendMessage(CB_GETEXTENDEDUI, 0, 0);
+ }
+
+ inline int CComboBox::GetHorizontalExtent() const
+ // Retrieve from the combo box the width, in pixels, by which the list box can
+ // be scrolled horizontally (the scrollable width).
+ {
+ assert(IsWindow());
+ return (int)SendMessage(CB_GETHORIZONTALEXTENT, 0, 0);
+ }
+
+ inline DWORD CComboBox::GetItemData(int nIndex) const
+ // Retrieves the application-supplied value associated with the specified item in the combo box.
+ {
+ assert(IsWindow());
+ return (DWORD)SendMessage(CB_GETITEMDATA, (WPARAM)nIndex, 0);
+ }
+
+ inline int CComboBox::GetItemHeight(int nIndex) const
+ // Determines the height of list items or the selection field in the combo box.
+ {
+ assert(IsWindow());
+ return (int)SendMessage(CB_GETITEMHEIGHT, (WPARAM)nIndex, 0);
+ }
+
+ inline int CComboBox::GetLBText(int nIndex, LPTSTR lpszText) const
+ // Retrieves a string from the list of the combo box.
+ {
+ assert(IsWindow());
+ return (int)SendMessage(CB_GETLBTEXT, (WPARAM)nIndex, (LPARAM)lpszText);
+ }
+
+ inline int CComboBox::GetLBTextLen(int nIndex) const
+ // Retrieves the length, in characters, of a string in the list of the combo box.
+ {
+ assert(IsWindow());
+ return (int)SendMessage(CB_GETLBTEXTLEN, (WPARAM)nIndex, 0);
+ }
+
+ inline LCID CComboBox::GetLocale() const
+ // Retrieves the current locale of the combo box.
+ {
+ assert(IsWindow());
+ return (LCID)SendMessage(CB_GETLOCALE, 0, 0);
+ }
+
+ inline int CComboBox::GetTopIndex() const
+ // Retrieves the zero-based index of the first visible item in the list box portion of the combo box.
+ {
+ assert(IsWindow());
+ return (int)SendMessage(CB_GETTOPINDEX, 0, 0);
+ }
+
+ inline int CComboBox::InitStorage(int nItems, int nBytes) const
+ // Allocates memory for storing list box items. Use this before adding a
+ // large number of items to the list box portion of a combo box.
+ {
+ assert(IsWindow());
+ return (int)SendMessage(CB_INITSTORAGE, (WPARAM)nItems, (LPARAM)nBytes);
+ }
+
+ inline int CComboBox::InsertString(int nIndex, LPCTSTR lpszString) const
+ // Inserts a string into the list box of the combo box. Unlike the AddString,
+ // a list with the CBS_SORT style is not sorted.
+ {
+ assert(IsWindow());
+ return (int)SendMessage(CB_INSERTSTRING, (WPARAM)nIndex, (LPARAM)lpszString);
+ }
+
+ inline void CComboBox::Paste() const
+ // Copies the current content of the clipboard to the combo box's edit control at the current caret position.
+ {
+ assert(IsWindow());
+ SendMessage(WM_PASTE, 0, 0);
+ }
+
+ inline void CComboBox::LimitText(int nMaxChars) const
+ // Limits the length of the text the user may type into the edit control of the combo box.
+ {
+ assert(IsWindow());
+ SendMessage(CB_LIMITTEXT, (WPARAM)nMaxChars, 0);
+ }
+
+ inline void CComboBox::ResetContent() const
+ // Removes all items from the list box and edit control of the combo box.
+ {
+ assert(IsWindow());
+ SendMessage(CB_RESETCONTENT, 0, 0);
+ }
+
+ inline int CComboBox::SelectString(int nStartAfter, LPCTSTR lpszString) const
+ // Searches the list of a combo box for an item that begins with the characters in a
+ // specified string. If a matching item is found, it is selected and copied to the edit control.
+ {
+ assert(IsWindow());
+ return (int)SendMessage(CB_SELECTSTRING, (WPARAM)nStartAfter, (LPARAM)lpszString);
+ }
+
+ inline int CComboBox::SetCurSel(int nIndex) const
+ // Selects a string in the list of the combo box. If necessary, the list scrolls the string into view.
+ {
+ assert(IsWindow());
+ return (int)SendMessage(CB_SETCURSEL, (WPARAM)nIndex, 0);
+ }
+
+ inline int CComboBox::SetDroppedWidth(int nWidth) const
+ // Sets the maximum allowable width, in pixels, of the list box of the combo box with
+ // the CBS_DROPDOWN or CBS_DROPDOWNLIST style.
+ {
+ assert(IsWindow());
+ return (int)SendMessage(CB_SETDROPPEDWIDTH, (WPARAM)nWidth, 0);
+ }
+
+ inline BOOL CComboBox::SetEditSel(int nStartChar, int nEndChar) const
+ // Selects characters in the edit control of the combo box.
+ {
+ assert(IsWindow());
+ return (BOOL)SendMessage(CB_SETEDITSEL, 0, (LPARAM)MAKELONG(nStartChar,nEndChar));
+ }
+
+ inline int CComboBox::SetExtendedUI(BOOL bExtended) const
+ // Selects either the default user interface or the extended user interface for the combo box that
+ // has the CBS_DROPDOWN or CBS_DROPDOWNLIST style.
+ {
+ assert(IsWindow());
+ return (int)SendMessage(CB_SETEXTENDEDUI, (WPARAM)bExtended, 0);
+ }
+
+ inline void CComboBox::SetHorizontalExtent(UINT nExtent ) const
+ // Sets the width, in pixels, by which the list box can be scrolled horizontally (the scrollable width).
+ {
+ assert(IsWindow());
+ SendMessage(CB_SETHORIZONTALEXTENT, (WPARAM)nExtent, 0);
+ }
+
+ inline int CComboBox::SetItemData(int nIndex, DWORD dwItemData) const
+ // Sets the value associated with the specified item in the combo box.
+ {
+ assert(IsWindow());
+ return (int)SendMessage(CB_SETITEMDATA, (WPARAM)nIndex, (LPARAM)dwItemData);
+ }
+
+ inline int CComboBox::SetItemHeight(int nIndex, UINT cyItemHeight) const
+ // Sets the height of list items or the selection field in the combo box.
+ {
+ assert(IsWindow());
+ return (int)SendMessage(CB_SETITEMHEIGHT, (WPARAM)nIndex, (LPARAM)cyItemHeight);
+ }
+
+ inline LCID CComboBox::SetLocale( LCID NewLocale ) const
+ // Sets the current locale of the combo box.
+ {
+ assert(IsWindow());
+ return (LCID)SendMessage(CB_SETLOCALE, (WPARAM)NewLocale, 0);
+ }
+
+ inline int CComboBox::SetTopIndex(int nIndex) const
+ // Ensure that a particular item is visible in the list box of the combo box.
+ {
+ assert(IsWindow());
+ return (int)SendMessage(CB_SETTOPINDEX, (WPARAM)nIndex, 0);
+ }
+
+ inline void CComboBox::ShowDropDown(BOOL bShow) const
+ // Shows or hides the list box of the combo box that has the CBS_DROPDOWN or CBS_DROPDOWNLIST style.
+ {
+ assert(IsWindow());
+ SendMessage(CB_SHOWDROPDOWN, (WPARAM)bShow, 0);
+ }
+
+
+ ////////////////////////////////////////
+ // Definitions for the CComboBoxEx class
+ //
+ inline int CComboBoxEx::DeleteItem(int nIndex ) const
+ // Removes an item from the ComboBoxEx control.
+ {
+ assert(IsWindow());
+ return (int)SendMessage(CBEM_DELETEITEM, (WPARAM)nIndex, 0);
+ }
+
+ inline CWnd* CComboBoxEx::GetComboBoxCtrl() const
+ // Retrieves the handle to the child combo box control.
+ {
+ assert(IsWindow());
+ return FromHandle((HWND)SendMessage(CBEM_GETCOMBOCONTROL, 0, 0));
+ }
+
+ inline CWnd* CComboBoxEx::GetEditCtrl() const
+ // Retrieves the handle to the edit control portion of the ComboBoxEx control.
+ {
+ assert(IsWindow());
+ return FromHandle((HWND)SendMessage(CBEM_GETEDITCONTROL, 0, 0));
+ }
+
+ inline DWORD CComboBoxEx::GetExtendedStyle() const
+ // Retrieves the extended styles that are in use for the ComboBoxEx control.
+ {
+ assert(IsWindow());
+ return (DWORD)SendMessage(CBEM_GETEXTENDEDSTYLE, 0, 0);
+ }
+
+ inline HIMAGELIST CComboBoxEx::GetImageList() const
+ // Retrieves the handle to an image list assigned to the ComboBoxEx control.
+ {
+ assert(IsWindow());
+ return (HIMAGELIST)SendMessage(CBEM_GETIMAGELIST, 0, 0);
+ }
+
+ inline BOOL CComboBoxEx::GetItem(COMBOBOXEXITEM* pCBItem) const
+ // Retrieves item information for the given ComboBoxEx item.
+ {
+ assert(IsWindow());
+ return (BOOL)SendMessage(CBEM_GETITEM, 0, (LPARAM)pCBItem);
+ }
+
+ inline BOOL CComboBoxEx::HasEditChanged () const
+ // Determines whether or not the user has changed the text of the ComboBoxEx edit control.
+ {
+ assert(IsWindow());
+ return (BOOL)SendMessage(CBEM_HASEDITCHANGED, 0, 0);
+ }
+
+ inline int CComboBoxEx::InsertItem(COMBOBOXEXITEM* lpcCBItem) const
+ // Inserts a new item in the ComboBoxEx control.
+ {
+ assert(IsWindow());
+ return (int)SendMessage(CBEM_INSERTITEM, 0, (LPARAM)lpcCBItem);
+ }
+
+ inline DWORD CComboBoxEx::SetExtendedStyle(DWORD dwExMask, DWORD dwExStyles ) const
+ // Sets extended styles within the ComboBoxEx control.
+ {
+ assert(IsWindow());
+ return (DWORD)SendMessage(CBEM_SETEXTENDEDSTYLE, (WPARAM)dwExMask, (LPARAM)dwExStyles);
+ }
+
+ inline HIMAGELIST CComboBoxEx::SetImageList(HIMAGELIST himl) const
+ // Sets an image list for the ComboBoxEx control.
+ {
+ assert(IsWindow());
+ return (HIMAGELIST)SendMessage(CBEM_SETIMAGELIST, 0, (LPARAM)himl);
+ }
+
+ inline BOOL CComboBoxEx::SetItem(PCOMBOBOXEXITEM lpcCBItem) const
+ // Sets the attributes for an item in the ComboBoxEx control.
+ {
+ assert(IsWindow());
+ return (BOOL)SendMessage(CBEM_SETITEM, 0, (LPARAM)lpcCBItem);
+ }
+
+
+ ////////////////////////////////////////
+ // Definitions for the CProgressBar class
+ //
+ inline int CProgressBar::GetPos() const
+ // Retrieves the current position of the progress bar.
+ {
+ assert(IsWindow());
+ return (int)SendMessage(PBM_GETPOS, 0, 0);
+ }
+
+ inline int CProgressBar::GetRange(BOOL fWhichLimit, PPBRANGE ppBRange) const
+ // Retrieves information about the current high and low limits of the progress bar control.
+ {
+ assert(IsWindow());
+ return (int)SendMessage(PBM_GETRANGE, (WPARAM)fWhichLimit, (LPARAM) (PPBRANGE) ppBRange);
+ }
+
+ inline int CProgressBar::OffsetPos(int nIncrement) const
+ // Advances the current position of the progress bar by a specified increment and redraws
+ // the bar to reflect the new position.
+ {
+ assert(IsWindow());
+ return (int)SendMessage(PBM_DELTAPOS, (WPARAM)nIncrement, 0);
+ }
+
+ inline int CProgressBar::SetPos(int nNewPos) const
+ // Sets the current position for the progress bar and redraws the bar to reflect the new position.
+ {
+ assert(IsWindow());
+ return (int)SendMessage(PBM_SETPOS, (WPARAM)nNewPos, 0);
+ }
+
+ inline int CProgressBar::SetRange(short nMinRange, short nMaxRange) const
+ // Sets the minimum and maximum values for the progress bar and redraws the bar to reflect the new range.
+ {
+ assert(IsWindow());
+ return (int)SendMessage(PBM_SETRANGE, 0, (LPARAM) MAKELPARAM (nMinRange, nMaxRange));
+ }
+
+ inline int CProgressBar::SetStep(int nStepInc) const
+ // Specifies the step increment for the progress bar.
+ {
+ assert(IsWindow());
+ return (int)SendMessage(PBM_SETSTEP, (WPARAM)nStepInc, 0);
+ }
+
+ inline int CProgressBar::StepIt() const
+ // Advances the current position for a progress bar by the step increment and
+ // redraws the bar to reflect the new position.
+ {
+ assert(IsWindow());
+ return (int)SendMessage(PBM_STEPIT, 0, 0);
+ }
+
+
+ ////////////////////////////////////////
+ // Definitions for the CScrollBar class
+ //
+ inline BOOL CScrollBar::EnableScrollBar( UINT nArrowFlags ) const
+ // Enables or disables the scroll bar arrows.
+ {
+ assert(IsWindow());
+ return ::EnableScrollBar(m_hWnd, SB_CTL, nArrowFlags);
+ }
+
+ inline BOOL CScrollBar::GetScrollInfo(LPSCROLLINFO lpsi) const
+ // Retrieves the parameters of a scroll bar, including the minimum and maximum
+ // scrolling positions, the page size, and the position of the scroll box (thumb).
+ {
+ assert(IsWindow());
+ return ::GetScrollInfo(m_hWnd, SB_CTL, lpsi);
+ }
+
+ inline int CScrollBar::GetScrollPos() const
+ // Retrieves the current position of the scroll box (thumb) in the scroll bar.
+ {
+ assert(IsWindow());
+ return ::GetScrollPos(m_hWnd, SB_CTL);
+ }
+
+ inline BOOL CScrollBar::GetScrollRange(LPINT lpMinPos, LPINT lpMaxPos ) const
+ // Retrieves the current minimum and maximum scroll box (thumb) positions for the scroll bar.
+ {
+ assert(IsWindow());
+ return ::GetScrollRange(m_hWnd, SB_CTL, lpMinPos, lpMaxPos);
+ }
+
+ inline BOOL CScrollBar::SetScrollInfo(LPSCROLLINFO lpsi, BOOL bRedraw ) const
+ // Sets the parameters of the scroll bar, including the minimum and maximum scrolling positions,
+ // the page size, and the position of the scroll box (thumb).
+ {
+ assert(IsWindow());
+ return ::SetScrollInfo(m_hWnd, SB_CTL, lpsi, bRedraw);
+ }
+
+ inline int CScrollBar::SetScrollPos(int nPos, BOOL bRedraw) const
+ // Sets the position of the scroll box (thumb) in the scroll bar and, if requested,
+ // redraws the scroll bar to reflect the new position of the scroll box.
+ {
+ assert(IsWindow());
+ return ::SetScrollPos(m_hWnd, SB_CTL, nPos, bRedraw);
+ }
+
+ inline BOOL CScrollBar::SetScrollRange( int nMinPos, int nMaxPos, BOOL bRedraw ) const
+ // Sets the minimum and maximum scroll box positions for the scroll bar.
+ {
+ assert(IsWindow());
+ return ::SetScrollRange(m_hWnd, SB_CTL, nMinPos, nMaxPos, bRedraw);
+ }
+
+ inline BOOL CScrollBar::ShowScrollBar(BOOL bShow) const
+ // Shows or hides the scroll bar.
+ {
+ assert(IsWindow());
+ return ::ShowScrollBar(m_hWnd, SB_CTL, bShow);
+ }
+
+ ////////////////////////////////////////
+ // Definitions for the CSlider class
+ //
+ inline void CSlider::ClearSel() const
+ // Clears the current selection range in the trackbar.
+ {
+ assert(IsWindow());
+ SendMessage(TBM_CLEARSEL, 0, 0);
+ }
+
+ inline void CSlider::ClearTics(BOOL bRedraw) const
+ // Removes the current tick marks from the trackbar.
+ {
+ assert(IsWindow());
+ SendMessage(TBM_CLEARTICS, (WPARAM)bRedraw, 0);
+ }
+
+ inline CWnd* CSlider::GetBuddy(BOOL fLocation) const
+ // Retrieves the handle to the trackbar control buddy window at a given location.
+ {
+ assert(IsWindow());
+ return FromHandle((HWND)SendMessage(TBM_GETBUDDY, (WPARAM)fLocation, 0));
+ }
+
+ inline CRect CSlider::GetChannelRect() const
+ // Retrieves the size and position of the bounding rectangle for the trackbar's channel.
+ {
+ assert(IsWindow());
+ CRect rc;
+ SendMessage(TBM_GETCHANNELRECT, 0, (LPARAM)&rc);
+ return rc;
+ }
+
+ inline int CSlider::GetLineSize() const
+ // Retrieves the number of logical positions the trackbar's slider moves in response
+ // to keyboard input from the arrow keys.
+ {
+ assert(IsWindow());
+ return (int)SendMessage(TBM_GETLINESIZE, 0, 0);
+ }
+
+ inline int CSlider::GetNumTics() const
+ // Retrieves the number of tick marks in the trackbar.
+ {
+ assert(IsWindow());
+ return (int)SendMessage(TBM_GETNUMTICS, 0, 0);
+ }
+
+ inline int CSlider::GetPageSize() const
+ // Retrieves the number of logical positions the trackbar's slider moves in response to
+ // keyboard input, or mouse input, such as clicks in the trackbar's channel.
+ {
+ assert(IsWindow());
+ return (int)SendMessage(TBM_GETPAGESIZE, 0, 0);
+ }
+
+ inline int CSlider::GetPos() const
+ // Retrieves the current logical position of the slider in the trackbar.
+ {
+ assert(IsWindow());
+ return (int)SendMessage(TBM_GETPOS, 0, 0);
+ }
+
+ inline int CSlider::GetRangeMax() const
+ // Retrieves the maximum position for the slider in the trackbar.
+ {
+ assert(IsWindow());
+ return (int)SendMessage(TBM_GETRANGEMAX, 0, 0);
+ }
+
+ inline int CSlider::GetRangeMin() const
+ // Retrieves the minimum position for the slider in the trackbar.
+ {
+ assert(IsWindow());
+ return (int)SendMessage(TBM_GETRANGEMIN, 0, 0);
+ }
+
+ inline int CSlider::GetSelEnd() const
+ // Retrieves the ending position of the current selection range in the trackbar.
+ {
+ assert(IsWindow());
+ return (int)SendMessage(TBM_GETSELEND, 0, 0);
+ }
+
+ inline int CSlider::GetSelStart() const
+ // Retrieves the starting position of the current selection range in the trackbar.
+ {
+ assert(IsWindow());
+ return (int)SendMessage(TBM_GETSELSTART, 0, 0);
+ }
+
+ inline int CSlider::GetThumbLength() const
+ // Retrieves the length of the slider in the trackbar.
+ {
+ assert(IsWindow());
+ return (int)SendMessage(TBM_GETTHUMBLENGTH, 0, 0);
+ }
+
+ inline CRect CSlider::GetThumbRect() const
+ // Retrieves the size and position of the bounding rectangle for the slider in the trackbar.
+ {
+ CRect rc;
+ SendMessage(TBM_GETTHUMBRECT, 0, (LPARAM)&rc);
+ return rc;
+ }
+
+ inline int CSlider::GetTic(int nTic ) const
+ // Retrieves the logical position of a tick mark in the trackbar.
+ {
+ assert(IsWindow());
+ return (int)SendMessage(TBM_GETTIC, (WPARAM)nTic, 0);
+ }
+
+ inline int CSlider::GetTicPos(int nTic) const
+ // Retrieves the current physical position of a tick mark in the trackbar.
+ {
+ assert(IsWindow());
+ return (int)SendMessage(TBM_GETTICPOS, (WPARAM)nTic, 0);
+ }
+
+ inline CWnd* CSlider::GetToolTips() const
+ // Retrieves the handle to the ToolTip control assigned to the trackbar, if any.
+ {
+ assert(IsWindow());
+ return FromHandle((HWND)SendMessage(TBM_GETTOOLTIPS, 0, 0));
+ }
+
+ inline CWnd* CSlider::SetBuddy(CWnd* pBuddy, BOOL fLocation /*= TRUE*/ ) const
+ // Assigns a window as the buddy window for the trackbar control.
+ {
+ assert(IsWindow());
+ return FromHandle((HWND)SendMessage(TBM_SETBUDDY, (WPARAM)fLocation, (LPARAM)pBuddy->GetHwnd()));
+ }
+
+ inline int CSlider::SetLineSize(int nSize) const
+ // Sets the number of logical positions the trackbar's slider moves in response to
+ // keyboard input from the arrow keys.
+ {
+ assert(IsWindow());
+ return(int)SendMessage(TBM_SETLINESIZE, 0, (LPARAM)nSize);
+ }
+
+ inline int CSlider::SetPageSize(int nSize) const
+ // Sets the number of logical positions the trackbar's slider moves in response to
+ // keyboard input, or mouse input such as clicks in the trackbar's channel.
+ {
+ assert(IsWindow());
+ return(int)SendMessage(TBM_SETPAGESIZE, 0, (LPARAM)nSize);
+ }
+
+ inline void CSlider::SetPos(int nPos, BOOL bRedraw) const
+ // Sets the current logical position of the slider in the trackbar.
+ {
+ assert(IsWindow());
+ SendMessage(TBM_SETPOS, (WPARAM)bRedraw, (LPARAM)nPos);
+ }
+
+ inline void CSlider::SetRangeMax(int nMax, BOOL bRedraw) const
+ // Sets the maximum logical position for the slider in the trackbar.
+ {
+ assert(IsWindow());
+ SendMessage(TBM_SETRANGEMAX, (WPARAM)bRedraw, (LPARAM)nMax);
+ }
+
+ inline void CSlider::SetRangeMin(int nMax, BOOL bRedraw) const
+ // Sets the minimum logical position for the slider in the trackbar.
+ {
+ assert(IsWindow());
+ SendMessage(TBM_SETRANGEMIN, (WPARAM)bRedraw, (LPARAM)nMax);
+ }
+
+ inline void CSlider::SetSelection(int nMin, int nMax, BOOL bRedraw) const
+ // Sets the starting and ending positions for the available selection range in the trackbar.
+ {
+ assert(IsWindow());
+ SendMessage(TBM_SETSEL, (WPARAM)bRedraw, (LPARAM)MAKELONG(nMax, nMin));
+ }
+
+ inline BOOL CSlider::SetTic(int nTic) const
+ // Sets a tick mark in the trackbar at the specified logical position.
+ {
+ assert(IsWindow());
+ return (BOOL)SendMessage(TBM_SETTIC, 0, nTic);
+ }
+
+ inline void CSlider::SetTicFreq(int nFreq) const
+ // Sets the interval frequency for tick marks in the trackbar.
+ {
+ assert(IsWindow());
+ SendMessage(TBM_SETTICFREQ, (WPARAM)nFreq, 0);
+ }
+
+ inline int CSlider::SetTipSide(int nLocation) const
+ // Positions a ToolTip control used by the trackbar control.
+ {
+ assert(IsWindow());
+ return (int)SendMessage(TBM_SETTIPSIDE, (WPARAM)nLocation, 0);
+ }
+
+ inline void CSlider::SetToolTips(CWnd* pToolTip) const
+ // Assigns a ToolTip control to the trackbar control.
+ {
+ assert(IsWindow());
+ SendMessage(TBM_SETTOOLTIPS, (WPARAM)pToolTip->GetHwnd(), 0);
+ }
+
+ ////////////////////////////////////////
+ // Definitions for the CSpinButton class
+ //
+ inline int CSpinButton::GetAccel(int cAccels, LPUDACCEL paAccels) const
+ // Retrieves acceleration information for the up-down control.
+ {
+ assert(IsWindow());
+ return (int)SendMessage(UDM_GETACCEL, (WPARAM)cAccels, (LPARAM)paAccels);
+ }
+
+ inline int CSpinButton::GetBase() const
+ // Retrieves the current radix base (that is, either base 10 or 16) for the up-down control.
+ {
+ assert(IsWindow());
+ return (int)SendMessage(UDM_GETBASE, 0, 0);
+ }
+
+ inline CWnd* CSpinButton::GetBuddy() const
+ // Retrieves the handle to the current buddy window.
+ {
+ assert(IsWindow());
+ return FromHandle((HWND)SendMessage(UDM_GETBUDDY, 0, 0));
+ }
+
+ inline int CSpinButton::GetPos() const
+ // Retrieves the current position of the up-down control with 16-bit precision.
+ {
+ assert(IsWindow());
+ return (int)SendMessage(UDM_GETPOS, 0, 0);
+ }
+
+ inline DWORD CSpinButton::GetRange() const
+ // Retrieves the minimum and maximum positions (range) for the up-down control.
+ {
+ assert(IsWindow());
+ return (DWORD)SendMessage(UDM_GETRANGE, 0, 0);
+ }
+
+ inline void CSpinButton::PreCreate(CREATESTRUCT &cs)
+ {
+ cs.style = WS_CHILD | WS_VISIBLE | WS_BORDER | WS_VISIBLE |UDS_SETBUDDYINT;
+ }
+
+ inline void CSpinButton::PreRegisterClass(WNDCLASS &wc)
+ {
+ wc.lpszClassName = UPDOWN_CLASS;
+ }
+
+ inline BOOL CSpinButton::SetAccel(int cAccels, LPUDACCEL paAccels) const
+ // Sets the acceleration for the up-down control.
+ {
+ assert(IsWindow());
+ return (BOOL)SendMessage(UDM_SETACCEL, (WPARAM)cAccels, (LPARAM)paAccels);
+ }
+
+ inline int CSpinButton::SetBase(int nBase) const
+ // Sets the radix base for the up-down control.
+ {
+ assert(IsWindow());
+ return (int)SendMessage(UDM_SETBASE, (WPARAM)nBase, 0);
+ }
+
+ inline CWnd* CSpinButton::SetBuddy(CWnd* pBuddy) const
+ // Sets the buddy window for the up-down control.
+ {
+ assert(IsWindow());
+ return FromHandle((HWND)SendMessage(UDM_SETBUDDY, (WPARAM)pBuddy->GetHwnd(), 0));
+ }
+
+ inline int CSpinButton::SetPos(int nPos) const
+ // Sets the current position for the up-down control with 16-bit precision.
+ {
+ assert(IsWindow());
+ return (int)SendMessage(UDM_SETPOS, 0, (LPARAM)MAKELONG ((short) nPos, 0));
+ }
+
+ inline void CSpinButton::SetRange(int nLower, int nUpper) const
+ // Sets the minimum and maximum positions (range) for the up-down control.
+ {
+ assert(IsWindow());
+ SendMessage(UDM_SETRANGE, 0, (LPARAM)MAKELONG(nUpper, nLower));
+ }
+
+} // namespace Win32xx
+
+#endif // define _WIN32XX_CONTROLS_H_
+
diff --git a/mmc_updater/depends/win32cpp/copyright.txt b/mmc_updater/depends/win32cpp/copyright.txt
new file mode 100644
index 00000000..d2222fa7
--- /dev/null
+++ b/mmc_updater/depends/win32cpp/copyright.txt
@@ -0,0 +1,33 @@
+Win32++ Version 7.2
+Released: 5th AUgust 2011
+
+ David Nash
+ email: dnash@bigpond.net.au
+ url: https://sourceforge.net/projects/win32-framework
+
+
+Copyright (c) 2005-2011 David Nash
+
+Permission is hereby granted, free of charge, to
+any person obtaining a copy of this software and
+associated documentation files (the "Software"),
+to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify,
+merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the
+following conditions:
+
+The above copyright notice and this permission notice
+shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
+OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/mmc_updater/depends/win32cpp/cstring.h b/mmc_updater/depends/win32cpp/cstring.h
new file mode 100644
index 00000000..faf574d5
--- /dev/null
+++ b/mmc_updater/depends/win32cpp/cstring.h
@@ -0,0 +1,905 @@
+// Win32++ Version 7.2
+// Released: 5th AUgust 2011
+//
+// David Nash
+// email: dnash@bigpond.net.au
+// url: https://sourceforge.net/projects/win32-framework
+//
+//
+// Copyright (c) 2005-2011 David Nash
+//
+// Permission is hereby granted, free of charge, to
+// any person obtaining a copy of this software and
+// associated documentation files (the "Software"),
+// to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify,
+// merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom
+// the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice
+// shall be included in all copies or substantial portions
+// of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
+// OR OTHER DEALINGS IN THE SOFTWARE.
+//
+////////////////////////////////////////////////////////
+
+
+// Acknowledgements:
+// Thanks to Adam Szulc for his initial CString code.
+
+////////////////////////////////////////////////////////
+// cstring.h
+// Declaration of the cstring.h
+
+// This class is intended to provide a simple alternative to the MFC/ATL
+// CString class that ships with Microsoft compilers. The CString class
+// specified here is compatible with other compilers such as Borland 5.5
+// and MinGW.
+
+// Differences between this class and the MFC/ATL CString class
+// ------------------------------------------------------------
+// 1) The constructors for this class accepts only TCHARs. The various text conversion
+// functions can be used to convert from other character types to TCHARs.
+//
+// 2) This class is not reference counted, so these CStrings should be passed as
+// references or const references when used as function arguments. As a result there
+// is no need for functions like LockBuffer and UnLockBuffer.
+//
+// 3) The Format functions only accepts POD (Plain Old Data) arguments. It does not
+// accept arguments which are class or struct objects. In particular it does not
+// accept CString objects, unless these are cast to LPCTSTR.
+// This is demonstrates valid and invalid usage:
+// CString string1(_T("Hello World"));
+// CString string2;
+//
+// // This is invalid, and produces undefined behaviour.
+// string2.Format(_T("String1 is: %s"), string1); // No! you can't do this
+//
+// // This is ok
+// string2.Format(_T("String1 is: %s"), (LPCTSTR)string1); // Yes, this is correct
+//
+// Note: The MFC/ATL CString class uses a non portable hack to make its CString class
+// behave like a POD. Other compilers (such as the MinGW compiler) specifically
+// prohibit the use of non POD types for functions with variable argument lists.
+//
+// 4) This class provides a few additional functions:
+// b_str Returns a BSTR string. This an an alternative for casting to BSTR.
+// c_str Returns a const TCHAR string. This is an alternative for casting to LPCTSTR.
+// GetErrorString Assigns CString to the error string for the specified System Error Code
+// (from ::GetLastErrror() for example).
+// GetString Returns a reference to the underlying std::basic_string<TCHAR>. This
+// reference can be used to modify the string directly.
+
+
+
+#ifndef _WIN32XX_CSTRING_H_
+#define _WIN32XX_CSTRING_H_
+
+
+#include "wincore.h"
+
+
+namespace Win32xx
+{
+
+ class CString
+ {
+ // friend functions allow the left hand side to be something other than CString
+ friend CString operator + (const CString& string1, const CString& string2);
+ friend CString operator + (const CString& string, LPCTSTR pszText);
+ friend CString operator + (const CString& string, TCHAR ch);
+ friend CString operator + (LPCTSTR pszText, const CString& string);
+ friend CString operator + (TCHAR ch, const CString& string);
+
+ public:
+ CString();
+ ~CString();
+ CString(const CString& str);
+ CString(LPCTSTR pszText);
+ CString(TCHAR ch, int nLength = 1);
+ CString(LPCTSTR pszText, int nLength);
+
+ CString& operator = (const CString& str);
+ CString& operator = (const TCHAR ch);
+ CString& operator = (LPCTSTR pszText);
+ BOOL operator == (LPCTSTR pszText);
+ BOOL operator != (LPCTSTR pszText);
+ BOOL operator < (LPCTSTR pszText);
+ BOOL operator > (LPCTSTR pszText);
+ BOOL operator <= (LPCTSTR pszText);
+ BOOL operator >= (LPCTSTR pszText);
+ operator LPCTSTR() const;
+ operator BSTR() const;
+ TCHAR& operator [] (int nIndex);
+ CString& operator += (const CString& str);
+
+ // Attributes
+ BSTR b_str() const { return T2W(m_str.c_str()); } // alternative for casting to BSTR
+ LPCTSTR c_str() const { return m_str.c_str(); } // alternative for casting to LPCTSTR
+ tString& GetString() { return m_str; } // returns a reference to the underlying std::basic_string<TCHAR>
+ int GetLength() const { return (int)m_str.length(); } // returns the length in characters
+
+ // Operations
+ BSTR AllocSysString() const;
+ void AppendFormat(LPCTSTR pszFormat,...);
+ void AppendFormat(UINT nFormatID, ...);
+ int Compare(LPCTSTR pszText) const;
+ int CompareNoCase(LPCTSTR pszText) const;
+ int Delete(int nIndex, int nCount = 1);
+ int Find(TCHAR ch, int nIndex = 0 ) const;
+ int Find(LPCTSTR pszText, int nStart = 0) const;
+ int FindOneOf(LPCTSTR pszText) const;
+ void Format(UINT nID, ...);
+ void Format(LPCTSTR pszFormat,...);
+ void FormatV(LPCTSTR pszFormat, va_list args);
+ void FormatMessage(LPCTSTR pszFormat,...);
+ void FormatMessageV(LPCTSTR pszFormat, va_list args);
+ TCHAR GetAt(int nIndex) const;
+ LPTSTR GetBuffer(int nMinBufLength);
+ void GetErrorString(DWORD dwError);
+ void Empty();
+ int Insert(int nIndex, TCHAR ch);
+ int Insert(int nIndex, const CString& str);
+ BOOL IsEmpty() const;
+ CString Left(int nCount) const;
+ BOOL LoadString(UINT nID);
+ void MakeLower();
+ void MakeReverse();
+ void MakeUpper();
+ CString Mid(int nFirst) const;
+ CString Mid(int nFirst, int nCount) const;
+ void ReleaseBuffer( int nNewLength = -1 );
+ int Remove(LPCTSTR pszText);
+ int Replace(TCHAR chOld, TCHAR chNew);
+ int Replace(const LPCTSTR pszOld, LPCTSTR pszNew);
+ int ReverseFind(LPCTSTR pszText, int nStart = -1) const;
+ CString Right(int nCount) const;
+ void SetAt(int nIndex, TCHAR ch);
+ BSTR SetSysString(BSTR* pBstr) const;
+ CString SpanExcluding(LPCTSTR pszText) const;
+ CString SpanIncluding(LPCTSTR pszText) const;
+ CString Tokenize(LPCTSTR pszTokens, int& iStart) const;
+ void Trim();
+ void TrimLeft();
+ void TrimLeft(TCHAR chTarget);
+ void TrimLeft(LPCTSTR pszTargets);
+ void TrimRight();
+ void TrimRight(TCHAR chTarget);
+ void TrimRight(LPCTSTR pszTargets);
+ void Truncate(int nNewLength);
+
+#ifndef _WIN32_WCE
+ int Collate(LPCTSTR pszText) const;
+ int CollateNoCase(LPCTSTR pszText) const;
+ BOOL GetEnvironmentVariable(LPCTSTR pszVar);
+#endif
+
+ private:
+ tString m_str;
+ std::vector<TCHAR> m_buf;
+ };
+
+ inline CString::CString()
+ {
+ }
+
+ inline CString::~CString()
+ {
+ }
+
+ inline CString::CString(const CString& str)
+ {
+ m_str.assign(str);
+ }
+
+ inline CString::CString(LPCTSTR pszText)
+ {
+ m_str.assign(pszText);
+ }
+
+ inline CString::CString(TCHAR ch, int nLength)
+ {
+ m_str.assign(nLength, ch);
+ }
+
+ inline CString::CString(LPCTSTR pszText, int nLength)
+ {
+ m_str.assign(pszText, nLength);
+ }
+
+ inline CString& CString::operator = (const CString& str)
+ {
+ m_str.assign(str);
+ return *this;
+ }
+
+ inline CString& CString::operator = (const TCHAR ch)
+ {
+ m_str.assign(1, ch);
+ return *this;
+ }
+
+ inline CString& CString::operator = (LPCTSTR pszText)
+ {
+ m_str.assign(pszText);
+ return *this;
+ }
+
+ inline BOOL CString::operator == (LPCTSTR pszText)
+ // Returns TRUE if the strings have the same content
+ {
+ assert(pszText);
+ return (0 == Compare(pszText));
+ }
+
+ inline BOOL CString::operator != (LPCTSTR pszText)
+ // Returns TRUE if the strings have a different content
+ {
+ assert(pszText);
+ return Compare(pszText) != 0;
+ }
+
+ inline BOOL CString::operator < (LPCTSTR pszText)
+ {
+ assert(pszText);
+ return Compare(pszText) < 0;
+ }
+
+ inline BOOL CString::operator > (LPCTSTR pszText)
+ {
+ assert(pszText);
+ return Compare(pszText) > 0;
+ }
+
+ inline BOOL CString::operator <= (LPCTSTR pszText)
+ {
+ assert(pszText);
+ return Compare(pszText) <= 0;
+ }
+
+ inline BOOL CString::operator >= (LPCTSTR pszText)
+ {
+ assert(pszText);
+ return Compare(pszText) >= 0;
+ }
+
+ inline CString::operator LPCTSTR() const
+ {
+ return m_str.c_str();
+ }
+
+ inline TCHAR& CString::operator [] (int nIndex)
+ {
+ assert(nIndex >= 0);
+ assert(nIndex < GetLength());
+ return m_str[nIndex];
+ }
+
+ inline CString& CString::operator += (const CString& str)
+ {
+ m_str.append(str);
+ return *this;
+ }
+
+ inline BSTR CString::AllocSysString() const
+ // Allocates a BSTR from the CString content.
+ {
+ return ::SysAllocStringLen(T2W(m_str.c_str()), (UINT)m_str.size());
+ }
+
+ inline void CString::AppendFormat(LPCTSTR pszFormat,...)
+ // Appends formatted data to an the CString content.
+ {
+ CString str;
+ str.Format(pszFormat);
+ m_str.append(str);
+ }
+
+ inline void CString::AppendFormat(UINT nFormatID, ...)
+ // Appends formatted data to an the CString content.
+ {
+ CString str1;
+ CString str2;
+ if (str1.LoadString(nFormatID))
+ {
+ str2.Format(str1);
+ m_str.append(str2);
+ }
+ }
+
+#ifndef _WIN32_WCE
+ inline int CString::Collate(LPCTSTR pszText) const
+ // Performs a case sensitive comparison of the two strings using locale-specific information.
+ {
+ assert(pszText);
+ return _tcscoll(m_str.c_str(), pszText);
+ }
+
+ inline int CString::CollateNoCase(LPCTSTR pszText) const
+ // Performs a case insensitive comparison of the two strings using locale-specific information.
+ {
+ assert(pszText);
+ return _tcsicoll(m_str.c_str(), pszText);
+ }
+#endif // _WIN32_WCE
+
+ inline int CString::Compare(LPCTSTR pszText) const
+ // Performs a case sensitive comparison of the two strings.
+ {
+ assert(pszText);
+ return m_str.compare(pszText);
+ }
+
+ inline int CString::CompareNoCase(LPCTSTR pszText) const
+ // Performs a case insensitive comparison of the two strings.
+ {
+ assert(pszText);
+ return _tcsicmp(m_str.data(), pszText);
+ }
+
+ inline int CString::Delete(int nIndex, int nCount /* = 1 */)
+ // Deletes a character or characters from the string.
+ {
+ assert(nIndex >= 0);
+ assert(nCount >= 0);
+
+ m_str.erase(nIndex, nCount);
+ return (int)m_str.size();
+ }
+
+ inline void CString::Empty()
+ // Erases the contents of the string.
+ {
+ m_str.erase();
+ }
+
+ inline int CString::Find(TCHAR ch, int nIndex /* = 0 */) const
+ // Finds a character in the string.
+ {
+ assert(nIndex >= 0);
+ return (int)m_str.find(ch, nIndex);
+ }
+
+ inline int CString::Find(LPCTSTR pszText, int nIndex /* = 0 */) const
+ // Finds a substring within the string.
+ {
+ assert(pszText);
+ assert(nIndex >= 0);
+ return (int)m_str.find(pszText, nIndex);
+ }
+
+ inline int CString::FindOneOf(LPCTSTR pszText) const
+ // Finds the first matching character from a set.
+ {
+ assert(pszText);
+ return (int)m_str.find_first_of(pszText);
+ }
+
+ inline void CString::Format(LPCTSTR pszFormat,...)
+ // Formats the string as sprintf does.
+ {
+ va_list args;
+ va_start(args, pszFormat);
+ FormatV(pszFormat, args);
+ va_end(args);
+ }
+
+ inline void CString::Format(UINT nID, ...)
+ // Formats the string as sprintf does.
+ {
+ Empty();
+ CString str;
+ if (str.LoadString(nID))
+ Format(str);
+ }
+
+ inline void CString::FormatV(LPCTSTR pszFormat, va_list args)
+ // Formats the string using a variable list of arguments.
+ {
+ if (pszFormat)
+ {
+ int nResult = -1, nLength = 256;
+
+ // A vector is used to store the TCHAR array
+ std::vector<TCHAR> vBuffer;( nLength+1, _T('\0') );
+
+ while (-1 == nResult)
+ {
+ vBuffer.assign( nLength+1, _T('\0') );
+ nResult = _vsntprintf(&vBuffer[0], nLength, pszFormat, args);
+ nLength *= 2;
+ }
+ m_str.assign(&vBuffer[0]);
+ }
+ }
+
+ inline void CString::FormatMessage(LPCTSTR pszFormat,...)
+ // Formats a message string.
+ {
+ va_list args;
+ va_start(args, pszFormat);
+ FormatMessageV(pszFormat, args);
+ va_end(args);
+ }
+
+ inline void CString::FormatMessageV(LPCTSTR pszFormat, va_list args)
+ // Formats a message string using a variable argument list.
+ {
+ LPTSTR pszTemp = 0;
+ if (pszFormat)
+ {
+ DWORD dwResult = ::FormatMessage(FORMAT_MESSAGE_FROM_STRING|FORMAT_MESSAGE_ALLOCATE_BUFFER, pszFormat, 0, 0, pszTemp, 0, &args);
+
+ if (0 == dwResult || 0 == pszTemp )
+ throw std::bad_alloc();
+
+ m_str = pszTemp;
+ LocalFree(pszTemp);
+ }
+ }
+
+ inline TCHAR CString::GetAt(int nIndex) const
+ // Returns the character at the specified location within the string.
+ {
+ assert(nIndex >= 0);
+ assert(nIndex < GetLength());
+ return m_str[nIndex];
+ }
+
+ inline LPTSTR CString::GetBuffer(int nMinBufLength)
+ // Creates a buffer of nMinBufLength charaters (+1 extra for NULL termination) and returns
+ // a pointer to this buffer. This buffer can be used by any function which accepts a LPTSTR.
+ // Care must be taken not to exceed the length of the buffer. Use ReleaseBuffer to safely
+ // copy this buffer back to the CString object.
+ //
+ // Note: The buffer uses a vector. Vectors are required to be contiguous in memory under
+ // the current standard, whereas std::strings do not have this requirement.
+ {
+ assert (nMinBufLength >= 0);
+
+ m_buf.assign(nMinBufLength + 1, _T('\0'));
+ tString::iterator it_end;
+
+ if (m_str.length() >= (size_t)nMinBufLength)
+ {
+ it_end = m_str.begin();
+ std::advance(it_end, nMinBufLength);
+ }
+ else
+ it_end = m_str.end();
+
+ std::copy(m_str.begin(), it_end, m_buf.begin());
+
+ return &m_buf[0];
+ }
+
+#ifndef _WIN32_WCE
+ inline BOOL CString::GetEnvironmentVariable(LPCTSTR pszVar)
+ // Sets the string to the value of the specified environment variable.
+ {
+ assert(pszVar);
+ Empty();
+
+ int nLength = ::GetEnvironmentVariable(pszVar, NULL, 0);
+ if (nLength > 0)
+ {
+ std::vector<TCHAR> vBuffer( nLength+1, _T('\0') );
+ ::GetEnvironmentVariable(pszVar, &vBuffer[0], nLength);
+ m_str = &vBuffer[0];
+ }
+
+ return (BOOL)nLength;
+ }
+#endif // _WIN32_WCE
+
+ inline void CString::GetErrorString(DWORD dwError)
+ // Returns the error string for the specified System Error Code (e.g from GetLastErrror).
+ {
+ m_str.erase();
+
+ if (dwError != 0)
+ {
+ TCHAR* pTemp = 0;
+ DWORD dwFlags = FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS;
+ ::FormatMessage(dwFlags, NULL, dwError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&pTemp, 1, NULL);
+ m_str.assign(pTemp);
+ ::LocalFree(pTemp);
+ }
+ }
+
+ inline int CString::Insert(int nIndex, TCHAR ch)
+ // Inserts a single character or a substring at the given index within the string.
+ {
+ assert(nIndex >= 0);
+ assert(ch);
+
+ m_str.insert(nIndex, &ch, 1);
+ return (int)m_str.size();
+ }
+
+ inline int CString::Insert(int nIndex, const CString& str)
+ // Inserts a single character or a substring at the given index within the string.
+ {
+ assert(nIndex >= 0);
+
+ m_str.insert(nIndex, str);
+ return (int)m_str.size();
+ }
+
+ inline BOOL CString::IsEmpty() const
+ // Returns TRUE if the string is empty
+ {
+ return m_str.empty();
+ }
+
+ inline CString CString::Left(int nCount) const
+ // Extracts the left part of a string.
+ {
+ assert(nCount >= 0);
+
+ CString str;
+ str.m_str.assign(c_str(), 0, nCount);
+ return str;
+ }
+
+ inline BOOL CString::LoadString(UINT nID)
+ // Loads the string from a Windows resource.
+ {
+ assert (GetApp());
+
+ int nSize = 64;
+ TCHAR* pTCharArray = 0;
+ std::vector<TCHAR> vString;
+ int nTChars = nSize;
+
+ Empty();
+
+ // Increase the size of our array in a loop until we load the entire string
+ // The ANSI and _UNICODE versions of LoadString behave differently. This technique works for both.
+ while ( nSize-1 <= nTChars )
+ {
+ nSize = nSize * 4;
+ vString.assign(nSize+1, _T('\0'));
+ pTCharArray = &vString[0];
+ nTChars = ::LoadString (GetApp()->GetResourceHandle(), nID, pTCharArray, nSize);
+ }
+
+ if (nTChars > 0)
+ m_str.assign(pTCharArray);
+
+ return (nTChars != 0);
+ }
+
+ inline void CString::MakeLower()
+ // Converts all the characters in this string to lowercase characters.
+ {
+ std::transform(m_str.begin(), m_str.end(), m_str.begin(), &::tolower);
+ }
+
+ inline void CString::MakeReverse()
+ // Reverses the string.
+ {
+ std::reverse(m_str.begin(), m_str.end());
+ }
+
+ inline void CString::MakeUpper()
+ // Converts all the characters in this string to uppercase characters.
+ {
+ std::transform(m_str.begin(), m_str.end(), m_str.begin(), &::toupper);
+ }
+
+ inline CString CString::Mid(int nFirst) const
+ // Extracts the middle part of a string.
+ {
+ return Mid(nFirst, GetLength());
+ }
+
+ inline CString CString::Mid(int nFirst, int nCount) const
+ // Extracts the middle part of a string.
+ {
+ assert(nFirst >= 0);
+ assert(nCount >= 0);
+
+ CString str;
+ str.m_str.assign(c_str(), nFirst, nFirst + nCount);
+ return str;
+ }
+
+ inline int CString::ReverseFind(LPCTSTR pszText, int nIndex /* = -1 */) const
+ // Search for a substring within the string, starting from the end.
+ {
+ assert(pszText);
+ return (int)m_str.rfind(pszText, nIndex);
+ }
+
+ inline void CString::SetAt(int nIndex, TCHAR ch)
+ // Sets the character at the specificed position to the specified value.
+ {
+ assert(nIndex >= 0);
+ assert(nIndex < GetLength());
+ m_str[nIndex] = ch;
+ }
+
+ inline void CString::ReleaseBuffer( int nNewLength /*= -1*/ )
+ // This copies the contents of the buffer (acquired by GetBuffer) to this CString,
+ // and releases the contents of the buffer. The default length of -1 copies from the
+ // buffer until a null terminator is reached. If the buffer doesn't contain a null
+ // terminator, you must specify the buffer's length.
+ {
+ assert (nNewLength > 0 || -1 == nNewLength);
+ assert (nNewLength < (int)m_buf.size());
+
+ if (-1 == nNewLength)
+ nNewLength = lstrlen(&m_buf[0]);
+ m_str.assign(nNewLength+1, _T('\0'));
+
+ std::vector<TCHAR>::iterator it_end = m_buf.begin();
+ std::advance(it_end, nNewLength);
+
+ std::copy(m_buf.begin(), it_end, m_str.begin());
+ m_buf.clear();
+ }
+
+ inline int CString::Remove(LPCTSTR pszText)
+ // Removes each occurrence of the specified substring from the string.
+ {
+ assert(pszText);
+
+ int nCount = 0;
+ size_t pos = 0;
+ while ((pos = m_str.find(pszText, pos)) != std::string::npos)
+ {
+ m_str.erase(pos, lstrlen(pszText));
+ ++nCount;
+ }
+ return nCount;
+ }
+
+ inline int CString::Replace(TCHAR chOld, TCHAR chNew)
+ // Replaces each occurance of the old character with the new character.
+ {
+ int nCount = 0;
+ tString::iterator it = m_str.begin();
+ while (it != m_str.end())
+ {
+ if (*it == chOld)
+ {
+ *it = chNew;
+ ++nCount;
+ }
+ ++it;
+ }
+ return nCount;
+ }
+
+ inline int CString::Replace(LPCTSTR pszOld, LPCTSTR pszNew)
+ // Replaces each occurance of the old substring with the new substring.
+ {
+ assert(pszOld);
+ assert(pszNew);
+
+ int nCount = 0;
+ size_t pos = 0;
+ while ((pos = m_str.find(pszOld, pos)) != std::string::npos)
+ {
+ m_str.replace(pos, lstrlen(pszOld), pszNew);
+ pos += lstrlen(pszNew);
+ ++nCount;
+ }
+ return nCount;
+ }
+
+ inline CString CString::Right(int nCount) const
+ // Extracts the right part of a string.
+ {
+ assert(nCount >= 0);
+
+ CString str;
+ str.m_str.assign(c_str(), m_str.size() - nCount, nCount);
+ return str;
+ }
+
+ inline BSTR CString::SetSysString(BSTR* pBstr) const
+ // Sets an existing BSTR object to the string.
+ {
+ assert(pBstr);
+
+ if ( !::SysReAllocStringLen(pBstr, T2W(m_str.c_str()), (UINT)m_str.length()) )
+ throw std::bad_alloc();
+
+ return *pBstr;
+ }
+
+ inline CString CString::SpanExcluding(LPCTSTR pszText) const
+ // Extracts characters from the string, starting with the first character,
+ // that are not in the set of characters identified by pszCharSet.
+ {
+ assert (pszText);
+
+ CString str;
+ size_t pos = 0;
+
+ while ((pos = m_str.find_first_not_of(pszText, pos)) != std::string::npos)
+ {
+ str.m_str.append(1, m_str[pos++]);
+ }
+
+ return str;
+ }
+
+ inline CString CString::SpanIncluding(LPCTSTR pszText) const
+ // Extracts a substring that contains only the characters in a set.
+ {
+ assert (pszText);
+
+ CString str;
+ size_t pos = 0;
+
+ while ((pos = m_str.find_first_of(pszText, pos)) != std::string::npos)
+ {
+ str.m_str.append(1, m_str[pos++]);
+ }
+
+ return str;
+ }
+
+ inline CString CString::Tokenize(LPCTSTR pszTokens, int& iStart) const
+ // Extracts specified tokens in a target string.
+ {
+ assert(pszTokens);
+ assert(iStart >= 0);
+
+ CString str;
+ size_t pos1 = m_str.find_first_not_of(pszTokens, iStart);
+ size_t pos2 = m_str.find_first_of(pszTokens, pos1);
+
+ iStart = (int)pos2 + 1;
+ if (pos2 == m_str.npos)
+ iStart = -1;
+
+ if (pos1 != m_str.npos)
+ str.m_str = m_str.substr(pos1, pos2-pos1);
+
+ return str;
+ }
+
+ inline void CString::Trim()
+ // Trims all leading and trailing whitespace characters from the string.
+ {
+ TrimLeft();
+ TrimRight();
+ }
+
+ inline void CString::TrimLeft()
+ // Trims leading whitespace characters from the string.
+ {
+ // This method is supported by the Borland 5.5 compiler
+ tString::iterator iter;
+ for (iter = m_str.begin(); iter < m_str.end(); ++iter)
+ {
+ if (!isspace(*iter))
+ break;
+ }
+
+ m_str.erase(m_str.begin(), iter);
+ }
+
+ inline void CString::TrimLeft(TCHAR chTarget)
+ // Trims the specified character from the beginning of the string.
+ {
+ m_str.erase(0, m_str.find_first_not_of(chTarget));
+ }
+
+ inline void CString::TrimLeft(LPCTSTR pszTargets)
+ // Trims the specified set of characters from the beginning of the string.
+ {
+ assert(pszTargets);
+ m_str.erase(0, m_str.find_first_not_of(pszTargets));
+ }
+
+ inline void CString::TrimRight()
+ // Trims trailing whitespace characters from the string.
+ {
+ // This method is supported by the Borland 5.5 compiler
+ tString::reverse_iterator riter;
+ for (riter = m_str.rbegin(); riter < m_str.rend(); ++riter)
+ {
+ if (!isspace(*riter))
+ break;
+ }
+
+ m_str.erase(riter.base(), m_str.end());
+ }
+
+ inline void CString::TrimRight(TCHAR chTarget)
+ // Trims the specified character from the end of the string.
+ {
+ size_t pos = m_str.find_last_not_of(chTarget);
+ if (pos != std::string::npos)
+ m_str.erase(++pos);
+ }
+
+ inline void CString::TrimRight(LPCTSTR pszTargets)
+ // Trims the specified set of characters from the end of the string.
+ {
+ assert(pszTargets);
+
+ size_t pos = m_str.find_last_not_of(pszTargets);
+ if (pos != std::string::npos)
+ m_str.erase(++pos);
+ }
+
+ inline void CString::Truncate(int nNewLength)
+ // Reduces the length of the string to the specified amount.
+ {
+ if (nNewLength < GetLength())
+ {
+ assert(nNewLength >= 0);
+ m_str.erase(nNewLength);
+ }
+ }
+
+
+ ///////////////////////////////////
+ // Global Functions
+ //
+
+ // friend functions of CString
+ inline CString operator + (const CString& string1, const CString& string2)
+ {
+ CString str(string1);
+ str.m_str.append(string2.m_str);
+ return str;
+ }
+
+ inline CString operator + (const CString& string, LPCTSTR pszText)
+ {
+ CString str(string);
+ str.m_str.append(pszText);
+ return str;
+ }
+
+ inline CString operator + (const CString& string, TCHAR ch)
+ {
+ CString str(string);
+ str.m_str.append(1, ch);
+ return str;
+ }
+
+ inline CString operator + (LPCTSTR pszText, const CString& string)
+ {
+ CString str(pszText);
+ str.m_str.append(string);
+ return str;
+ }
+
+ inline CString operator + (TCHAR ch, const CString& string)
+ {
+ CString str(ch);
+ str.m_str.append(string);
+ return str;
+ }
+
+ // Global LoadString
+ inline CString LoadString(UINT nID)
+ {
+ CString str;
+ str.LoadString(nID);
+ return str;
+ }
+
+
+} // namespace Win32xx
+
+#endif//_WIN32XX_CSTRING_H_
diff --git a/mmc_updater/depends/win32cpp/default_resource.h b/mmc_updater/depends/win32cpp/default_resource.h
new file mode 100644
index 00000000..b616a183
--- /dev/null
+++ b/mmc_updater/depends/win32cpp/default_resource.h
@@ -0,0 +1,94 @@
+// This file contains the resource ID definitions for Win32++.
+
+
+// The resource ID for MENU, ICON, ToolBar Bitmap, Accelerator,
+// and Window Caption
+#define IDW_MAIN 51
+
+// Resource ID for the About dialog
+#define IDW_ABOUT 52
+
+// Resource IDs for menu items
+#define IDW_VIEW_TOOLBAR 53
+#define IDW_VIEW_STATUSBAR 54
+
+// Resource IDs for the Command Bands
+#define IDW_CMD_BANDS 55
+#define IDW_MENUBAR 56
+#define IDW_TOOLBAR 57
+
+// Resource ID for the Accelerator key
+#define IDW_QUIT 58
+
+// Resource IDs for MDI menu items
+#define IDW_MDI_CASCADE 60
+#define IDW_MDI_TILE 61
+#define IDW_MDI_ARRANGE 62
+#define IDW_MDI_CLOSEALL 63
+#define IDW_FIRSTCHILD 64
+#define IDW_CHILD2 65
+#define IDW_CHILD3 66
+#define IDW_CHILD4 67
+#define IDW_CHILD5 68
+#define IDW_CHILD6 69
+#define IDW_CHILD7 70
+#define IDW_CHILD8 71
+#define IDW_CHILD9 72
+#define IDW_CHILD10 73
+
+#define IDW_FILE_MRU_FILE1 75
+#define IDW_FILE_MRU_FILE2 76
+#define IDW_FILE_MRU_FILE3 77
+#define IDW_FILE_MRU_FILE4 78
+#define IDW_FILE_MRU_FILE5 79
+#define IDW_FILE_MRU_FILE6 80
+#define IDW_FILE_MRU_FILE7 81
+#define IDW_FILE_MRU_FILE8 82
+#define IDW_FILE_MRU_FILE9 83
+#define IDW_FILE_MRU_FILE10 84
+#define IDW_FILE_MRU_FILE11 85
+#define IDW_FILE_MRU_FILE12 86
+#define IDW_FILE_MRU_FILE13 87
+#define IDW_FILE_MRU_FILE14 88
+#define IDW_FILE_MRU_FILE15 89
+#define IDW_FILE_MRU_FILE16 90
+
+// Cursor Resources
+#define IDW_SPLITH 91
+#define IDW_SPLITV 92
+#define IDW_TRACK4WAY 93
+
+// Docking Bitmap Resources
+#define IDW_SDBOTTOM 94
+#define IDW_SDCENTER 95
+#define IDW_SDLEFT 96
+#define IDW_SDMIDDLE 97
+#define IDW_SDRIGHT 98
+#define IDW_SDTOP 99
+
+
+// A generic ID for any static control
+#ifndef IDC_STATIC
+ #define IDC_STATIC -1
+#endif
+
+
+
+// Notes about Resource IDs
+// * In general, resource IDs can have values from 1 to 65535. Programs with
+// resource IDs higher than 65535 aren't supported on Windows 95
+//
+// * CMenuBar uses resource IDs beginning from 0 for the top level menu items.
+// Win32++ leaves resource IDs below 51 unallocated for top level menu items.
+//
+// * Windows uses the icon with the lowest resource ID as the application's
+// icon. The application's icon is IDW_MAIN, which is the first resource ID
+// defined by Win32++.
+//
+// * When more than one static control is used in a dialog, the controls should
+// have a unique ID, unless a resource ID of -1 is used.
+//
+// * Users of Win32++ are advised to begin their resource IDs from 120 to
+// allow for possible expansion of Win32++.
+
+
diff --git a/mmc_updater/depends/win32cpp/default_resource.rc b/mmc_updater/depends/win32cpp/default_resource.rc
new file mode 100644
index 00000000..d53479f5
--- /dev/null
+++ b/mmc_updater/depends/win32cpp/default_resource.rc
@@ -0,0 +1,250 @@
+// An example of a resource file
+//
+
+#include "resource.h"
+#include "windows.h"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// RT_MANIFEST
+//
+
+1 24 DISCARDABLE "res/Win32++.manifest"
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Menu
+//
+
+
+IDW_MAIN MENU
+BEGIN
+ POPUP "&File"
+ BEGIN
+ MENUITEM "New &View", IDM_FILE_NEWVIEW
+ MENUITEM SEPARATOR
+ MENUITEM "Recent Files", IDW_FILE_MRU_FILE1, GRAYED
+ MENUITEM SEPARATOR
+ MENUITEM "E&xit", IDM_FILE_EXIT
+ END
+ POPUP "&Edit"
+ BEGIN
+ MENUITEM "Undo\tCtrl+Z", IDM_EDIT_UNDO
+ MENUITEM "Redo\tShift+Ctrl+Z", IDM_EDIT_REDO
+ MENUITEM SEPARATOR
+ MENUITEM "Cut\tCtrl+X", IDM_EDIT_CUT
+ MENUITEM "Copy\tCtrl+C", IDM_EDIT_COPY
+ MENUITEM "Paste\tCtrl+V", IDM_EDIT_PASTE
+ MENUITEM "Delete\tDel", IDM_EDIT_DELETE
+ END
+ POPUP "&View"
+ BEGIN
+ MENUITEM "&Tool Bar", IDW_VIEW_TOOLBAR, CHECKED
+ MENUITEM "&Status Bar", IDW_VIEW_STATUSBAR, CHECKED
+ END
+ POPUP "&Help"
+ BEGIN
+ MENUITEM "&About", IDM_HELP_ABOUT
+ END
+END
+
+MDIMENUVIEW MENU
+BEGIN
+ POPUP "&File"
+ BEGIN
+ MENUITEM "New &View", IDM_FILE_NEWVIEW
+ MENUITEM "&Close", IDM_FILE_CLOSE
+ MENUITEM SEPARATOR
+ MENUITEM "E&xit", IDM_FILE_EXIT
+ END
+ POPUP "&Edit"
+ BEGIN
+ MENUITEM "Undo", IDM_EDIT_UNDO
+ MENUITEM "Redo", IDM_EDIT_REDO
+ MENUITEM SEPARATOR
+ MENUITEM "Cu&t", IDM_EDIT_CUT
+ MENUITEM "&Copy", IDM_EDIT_COPY
+ MENUITEM "&Paste", IDM_EDIT_PASTE
+ MENUITEM "De&lete", IDM_EDIT_DELETE
+ END
+ POPUP "&View"
+ BEGIN
+ MENUITEM "Tool Bar", IDW_VIEW_TOOLBAR, CHECKED
+ MENUITEM "Status Bar", IDW_VIEW_STATUSBAR, CHECKED
+ END
+ POPUP "&Color"
+ BEGIN
+ MENUITEM "&Black", IDM_COLOR_BLACK
+ MENUITEM "&Red", IDM_COLOR_RED
+ MENUITEM "&Green", IDM_COLOR_GREEN
+ MENUITEM "B&lue", IDM_COLOR_BLUE
+ MENUITEM "&White", IDM_COLOR_WHITE
+ END
+ POPUP "&Window"
+ BEGIN
+ MENUITEM "&Cascade\tShift+F5", IDW_WINDOW_CASCADE
+ MENUITEM "&Tile\tShift+F4", IDW_WINDOW_TILE
+ MENUITEM "Arrange &Icons", IDW_WINDOW_ARRANGE
+ MENUITEM "Close &All", IDW_WINDOW_CLOSEALL
+ END
+ POPUP "&Help"
+ BEGIN
+ MENUITEM "About", IDM_HELP_ABOUT
+ END
+END
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDW_MAIN ICON "res/mdi.ico"
+IDI_VIEW ICON "res/view.ico"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Bitmap
+//
+
+IDW_MAIN BITMAP "res/toolbar.bmp"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDW_ABOUT DIALOGEX 0, 0, 186, 90
+STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION |
+ WS_SYSMENU
+CAPTION "About"
+FONT 8, "MS Shell Dlg", 400, 0
+BEGIN
+ DEFPUSHBUTTON "OK",IDOK,68,49,50,14
+ CTEXT "MDI Frame",IDC_STATIC,60,22,64,11
+ ICON IDW_MAIN,0,4,4,20,20
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Accelerator
+//
+
+IDW_MAIN ACCELERATORS
+BEGIN
+ "N", IDM_FILE_NEW, VIRTKEY, CONTROL, NOINVERT
+ "O", IDM_FILE_OPEN, VIRTKEY, CONTROL, NOINVERT
+ "P", IDM_FILE_PRINT, VIRTKEY, CONTROL, NOINVERT
+ "S", IDM_FILE_SAVE, VIRTKEY, CONTROL, NOINVERT
+ "C", IDM_EDIT_COPY, VIRTKEY, CONTROL, NOINVERT
+ "X", IDM_EDIT_CUT, VIRTKEY, CONTROL, NOINVERT
+ "V", IDM_EDIT_PASTE, VIRTKEY, CONTROL, NOINVERT
+ "Z", IDM_EDIT_UNDO, VIRTKEY, CONTROL, NOINVERT
+ "Y", IDM_EDIT_REDO, VIRTKEY, SHIFT, CONTROL, NOINVERT
+ VK_DELETE, IDM_EDIT_DELETE, VIRTKEY, NOINVERT
+END
+
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// String Table
+//
+
+STRINGTABLE
+BEGIN
+ IDW_MAIN "MDI Frame"
+END
+
+STRINGTABLE
+BEGIN
+ IDM_FILE_NEW "Create a New Document"
+ IDM_FILE_OPEN "Open Existing Document"
+ IDM_FILE_SAVE "Save the Document"
+ IDM_FILE_SAVEAS "Save the Document with a new name"
+ IDM_FILE_PRINT "Print the Document"
+ IDM_FILE_EXIT "End the Program"
+END
+
+STRINGTABLE
+BEGIN
+ IDM_EDIT_UNDO "Undo the last action"
+ IDM_EDIT_REDO "Redo the previously undone action"
+ IDM_EDIT_CUT "Cut the Selected Contents to the Clipboard"
+ IDM_EDIT_COPY "Copy the Selected Contents to the Clipboard"
+ IDM_EDIT_PASTE "Paste the Clipboard Contents to the Document"
+ IDM_EDIT_DELETE "Erase the selected Contents"
+ IDW_VIEW_TOOLBAR "Show or hide the tool bar"
+ IDW_VIEW_STATUSBAR "Show or hide the status bar"
+END
+
+STRINGTABLE
+BEGIN
+ IDM_HELP_ABOUT "Display Information about this program"
+END
+
+STRINGTABLE
+BEGIN
+ IDW_FIRSTCHILD "Activate this window"
+ IDW_CHILD2 "Activate this window"
+ IDW_CHILD3 "Activate this window"
+ IDW_CHILD4 "Activate this window"
+ IDW_CHILD5 "Activate this window"
+ IDW_CHILD6 "Activate this window"
+ IDW_CHILD7 "Activate this window"
+ IDW_CHILD8 "Activate this window"
+ IDW_CHILD9 "Activate this window"
+ IDW_CHILD10 "Select a window"
+END
+
+STRINGTABLE
+BEGIN
+ IDM_FILE_NEWVIEW "Create View MDI Child"
+ IDM_FILE_CLOSE "Close MDI Window"
+ IDM_COLOR_BLACK "Use Black Printing"
+ IDM_COLOR_RED "Use Red Printing"
+ IDM_COLOR_GREEN "Use Green Printing"
+ IDM_COLOR_BLUE "Use Blue Printing"
+ IDM_COLOR_WHITE "Use White Printing"
+ IDW_WINDOW_CASCADE "Cascade MDI Windows"
+ IDW_WINDOW_TILE "Tile MDI Windows"
+ IDW_WINDOW_ARRANGE "Arrange Icons"
+ IDW_WINDOW_CLOSEALL "Close All MDI Windows"
+END
+
+STRINGTABLE
+BEGIN
+ SC_CLOSE "Close the Window"
+ SC_MAXIMIZE "Maximize the Window"
+ SC_MINIMIZE "Minimize the WIndow"
+ SC_MOVE "Move the Window"
+ SC_NEXTWINDOW "Select Next Window"
+ SC_PREVWINDOW "Select Previous Window"
+ SC_RESTORE "Restore the Window"
+ SC_SIZE "Resize the Window"
+END
+
+STRINGTABLE
+BEGIN
+ IDW_FILE_MRU_FILE1 "Open this document"
+ IDW_FILE_MRU_FILE2 "Open this document"
+ IDW_FILE_MRU_FILE3 "Open this document"
+ IDW_FILE_MRU_FILE4 "Open this document"
+ IDW_FILE_MRU_FILE5 "Open this document"
+ IDW_FILE_MRU_FILE6 "Open this document"
+ IDW_FILE_MRU_FILE7 "Open this document"
+ IDW_FILE_MRU_FILE8 "Open this document"
+ IDW_FILE_MRU_FILE9 "Open this document"
+ IDW_FILE_MRU_FILE10 "Open this document"
+ IDW_FILE_MRU_FILE11 "Open this document"
+ IDW_FILE_MRU_FILE12 "Open this document"
+ IDW_FILE_MRU_FILE13 "Open this document"
+ IDW_FILE_MRU_FILE14 "Open this document"
+ IDW_FILE_MRU_FILE15 "Open this document"
+ IDW_FILE_MRU_FILE16 "Open this document"
+END
+
+
diff --git a/mmc_updater/depends/win32cpp/dialog.h b/mmc_updater/depends/win32cpp/dialog.h
new file mode 100644
index 00000000..e5123304
--- /dev/null
+++ b/mmc_updater/depends/win32cpp/dialog.h
@@ -0,0 +1,876 @@
+// Win32++ Version 7.2
+// Released: 5th AUgust 2011
+//
+// David Nash
+// email: dnash@bigpond.net.au
+// url: https://sourceforge.net/projects/win32-framework
+//
+//
+// Copyright (c) 2005-2011 David Nash
+//
+// Permission is hereby granted, free of charge, to
+// any person obtaining a copy of this software and
+// associated documentation files (the "Software"),
+// to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify,
+// merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom
+// the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice
+// shall be included in all copies or substantial portions
+// of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
+// OR OTHER DEALINGS IN THE SOFTWARE.
+//
+////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////
+// dialog.h
+// Declaration of the CDialog class
+
+// CDialog adds support for dialogs to Win32++. Dialogs are specialised
+// windows which are a parent window for common controls. Common controls
+// are special window types such as buttons, edit controls, tree views,
+// list views, static text etc.
+
+// The layout of a dialog is typically defined in a resource script file
+// (often Resource.rc). While this script file can be constructed manually,
+// it is often created using a resource editor. If your compiler doesn't
+// include a resource editor, you might find ResEdit useful. It is a free
+// resource editor available for download at:
+// http://www.resedit.net/
+
+// CDialog supports modal and modeless dialogs. It also supports the creation
+// of dialogs defined in a resource script file, as well as those defined in
+// a dialog template.
+
+// Use the Dialog generic program as the starting point for your own dialog
+// applications.
+// The DlgSubclass sample demonstrates how to use subclassing to customise
+// the behaviour of common controls in a dialog.
+
+
+#ifndef _WIN32XX_DIALOG_H_
+#define _WIN32XX_DIALOG_H_
+
+#include "wincore.h"
+
+#ifndef SWP_NOCOPYBITS
+ #define SWP_NOCOPYBITS 0x0100
+#endif
+
+namespace Win32xx
+{
+
+ class CDialog : public CWnd
+ {
+ public:
+ CDialog(UINT nResID, CWnd* pParent = NULL);
+ CDialog(LPCTSTR lpszResName, CWnd* pParent = NULL);
+ CDialog(LPCDLGTEMPLATE lpTemplate, CWnd* pParent = NULL);
+ virtual ~CDialog();
+
+ // You probably won't need to override these functions
+ virtual void AttachItem(int nID, CWnd& Wnd);
+ virtual HWND Create(CWnd* pParent = NULL);
+ virtual INT_PTR DoModal();
+ virtual HWND DoModeless();
+ virtual void SetDlgParent(CWnd* pParent);
+ BOOL IsModal() const { return m_IsModal; }
+ BOOL IsIndirect() const { return (NULL != m_lpTemplate); }
+
+ protected:
+ // These are the functions you might wish to override
+ virtual INT_PTR DialogProc(UINT uMsg, WPARAM wParam, LPARAM lParam);
+ virtual INT_PTR DialogProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam);
+ virtual void EndDialog(INT_PTR nResult);
+ virtual void OnCancel();
+ virtual BOOL OnInitDialog();
+ virtual void OnOK();
+ virtual BOOL PreTranslateMessage(MSG* pMsg);
+
+ // Can't override these functions
+ static INT_PTR CALLBACK StaticDialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
+
+ #ifndef _WIN32_WCE
+ static LRESULT CALLBACK StaticMsgHook(int nCode, WPARAM wParam, LPARAM lParam);
+ #endif
+
+ private:
+ CDialog(const CDialog&); // Disable copy construction
+ CDialog& operator = (const CDialog&); // Disable assignment operator
+
+ BOOL m_IsModal; // a flag for modal dialogs
+ LPCTSTR m_lpszResName; // the resource name for the dialog
+ LPCDLGTEMPLATE m_lpTemplate; // the dialog template for indirect dialogs
+ HWND m_hParent; // handle to the dialogs's parent window
+ };
+
+
+#ifndef _WIN32_WCE
+
+ //////////////////////////////////////
+ // Declaration of the CResizer class
+ //
+ // The CResizer class can be used to rearrange a dialog's child
+ // windows when the dialog is resized.
+
+ // To use CResizer, follow the following steps:
+ // 1) Use Initialize to specify the dialog's CWnd, and min and max size.
+ // 3) Use AddChild for each child window
+ // 4) Call HandleMessage from within DialogProc.
+ //
+
+ // Resize Dialog Styles
+#define RD_STRETCH_WIDTH 0x0001 // The item has a variable width
+#define RD_STRETCH_HEIGHT 0x0002 // The item has a variable height
+
+ // Resize Dialog alignments
+ enum Alignment { topleft, topright, bottomleft, bottomright };
+
+ class CResizer
+ {
+ public:
+ CResizer() : m_pParent(0), m_xScrollPos(0), m_yScrollPos(0) {}
+ virtual ~CResizer() {}
+
+ virtual void AddChild(CWnd* pWnd, Alignment corner, DWORD dwStyle);
+ virtual void AddChild(HWND hWnd, Alignment corner, DWORD dwStyle);
+ virtual void HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam);
+ virtual void Initialize(CWnd* pParent, RECT rcMin, RECT rcMax = CRect(0,0,0,0));
+ virtual void OnHScroll(WPARAM wParam, LPARAM lParam);
+ virtual void OnVScroll(WPARAM wParam, LPARAM lParam);
+ virtual void RecalcLayout();
+ CRect GetMinRect() const { return m_rcMin; }
+ CRect GetMaxRect() const { return m_rcMax; }
+
+ struct ResizeData
+ {
+ CRect rcInit;
+ CRect rcOld;
+ Alignment corner;
+ BOOL bFixedWidth;
+ BOOL bFixedHeight;
+ HWND hWnd;
+ };
+
+ private:
+ CWnd* m_pParent;
+ std::vector<ResizeData> m_vResizeData;
+
+ CRect m_rcInit;
+ CRect m_rcMin;
+ CRect m_rcMax;
+
+ int m_xScrollPos;
+ int m_yScrollPos;
+ };
+
+#endif
+
+}
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+namespace Win32xx
+{
+ ////////////////////////////////////
+ // Definitions for the CDialog class
+ //
+ inline CDialog::CDialog(LPCTSTR lpszResName, CWnd* pParent/* = NULL*/)
+ : m_IsModal(TRUE), m_lpszResName(lpszResName), m_lpTemplate(NULL)
+ {
+ m_hParent = pParent? pParent->GetHwnd() : NULL;
+ ::InitCommonControls();
+ }
+
+ inline CDialog::CDialog(UINT nResID, CWnd* pParent/* = NULL*/)
+ : m_IsModal(TRUE), m_lpszResName(MAKEINTRESOURCE (nResID)), m_lpTemplate(NULL)
+ {
+ m_hParent = pParent? pParent->GetHwnd() : NULL;
+ ::InitCommonControls();
+ }
+
+ //For indirect dialogs - created from a dialog box template in memory.
+ inline CDialog::CDialog(LPCDLGTEMPLATE lpTemplate, CWnd* pParent/* = NULL*/)
+ : m_IsModal(TRUE), m_lpszResName(NULL), m_lpTemplate(lpTemplate)
+ {
+ m_hParent = pParent? pParent->GetHwnd() : NULL;
+ ::InitCommonControls();
+ }
+
+ inline CDialog::~CDialog()
+ {
+ if (m_hWnd != NULL)
+ {
+ if (IsModal())
+ ::EndDialog(m_hWnd, 0);
+ else
+ Destroy();
+ }
+ }
+
+ inline void CDialog::AttachItem(int nID, CWnd& Wnd)
+ // Attach a dialog item to a CWnd
+ {
+ Wnd.AttachDlgItem(nID, this);
+ }
+
+ inline HWND CDialog::Create(CWnd* pParent /* = NULL */)
+ {
+ // Allow a dialog to be used as a child window
+
+ assert(GetApp());
+ SetDlgParent(pParent);
+ return DoModeless();
+ }
+
+ inline INT_PTR CDialog::DialogProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
+ {
+ // Override this function in your class derrived from CDialog if you wish to handle messages
+ // A typical function might look like this:
+
+ // switch (uMsg)
+ // {
+ // case MESSAGE1: // Some Windows API message
+ // OnMessage1(); // A user defined function
+ // break; // Also do default processing
+ // case MESSAGE2:
+ // OnMessage2();
+ // return x; // Don't do default processing, but instead return
+ // // a value recommended by the Windows API documentation
+ // }
+
+ // Always pass unhandled messages on to DialogProcDefault
+ return DialogProcDefault(uMsg, wParam, lParam);
+ }
+
+ inline INT_PTR CDialog::DialogProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam)
+ // All DialogProc functions should pass unhandled messages to this function
+ {
+ LRESULT lr = 0;
+
+ switch (uMsg)
+ {
+ case UWM_CLEANUPTEMPS:
+ {
+ TLSData* pTLSData = (TLSData*)TlsGetValue(GetApp()->GetTlsIndex());
+ pTLSData->vTmpWnds.clear();
+ }
+ break;
+ case WM_INITDIALOG:
+ {
+ // Center the dialog
+ CenterWindow();
+ }
+ return OnInitDialog();
+ case WM_COMMAND:
+ switch (LOWORD (wParam))
+ {
+ case IDOK:
+ OnOK();
+ return TRUE;
+ case IDCANCEL:
+ OnCancel();
+ return TRUE;
+ default:
+ {
+ // Refelect this message if it's from a control
+ CWnd* pWnd = GetApp()->GetCWndFromMap((HWND)lParam);
+ if (pWnd != NULL)
+ lr = pWnd->OnCommand(wParam, lParam);
+
+ // Handle user commands
+ if (!lr)
+ lr = OnCommand(wParam, lParam);
+
+ if (lr) return 0L;
+ }
+ break; // Some commands require default processing
+ }
+ break;
+
+ case WM_NOTIFY:
+ {
+ // Do Notification reflection if it came from a CWnd object
+ HWND hwndFrom = ((LPNMHDR)lParam)->hwndFrom;
+ CWnd* pWndFrom = GetApp()->GetCWndFromMap(hwndFrom);
+
+ if (pWndFrom != NULL)
+ lr = pWndFrom->OnNotifyReflect(wParam, lParam);
+ else
+ {
+ // Some controls (eg ListView) have child windows.
+ // Reflect those notifications too.
+ CWnd* pWndFromParent = GetApp()->GetCWndFromMap(::GetParent(hwndFrom));
+ if (pWndFromParent != NULL)
+ lr = pWndFromParent->OnNotifyReflect(wParam, lParam);
+ }
+
+ // Handle user notifications
+ if (!lr) lr = OnNotify(wParam, lParam);
+
+ // Set the return code for notifications
+ if (IsWindow())
+ SetWindowLongPtr(DWLP_MSGRESULT, (LONG_PTR)lr);
+
+ return (BOOL)lr;
+ }
+
+ case WM_PAINT:
+ {
+ if (::GetUpdateRect(m_hWnd, NULL, FALSE))
+ {
+ CPaintDC dc(this);
+ OnDraw(&dc);
+ }
+ else
+ // RedrawWindow can require repainting without an update rect
+ {
+ CClientDC dc(this);
+ OnDraw(&dc);
+ }
+
+ break;
+ }
+
+ case WM_ERASEBKGND:
+ {
+ CDC dc((HDC)wParam);
+ BOOL bResult = OnEraseBkgnd(&dc);
+ dc.Detach();
+ if (bResult) return TRUE;
+ }
+ break;
+
+ // A set of messages to be reflected back to the control that generated them
+ case WM_CTLCOLORBTN:
+ case WM_CTLCOLOREDIT:
+ case WM_CTLCOLORDLG:
+ case WM_CTLCOLORLISTBOX:
+ case WM_CTLCOLORSCROLLBAR:
+ case WM_CTLCOLORSTATIC:
+ case WM_DRAWITEM:
+ case WM_MEASUREITEM:
+ case WM_DELETEITEM:
+ case WM_COMPAREITEM:
+ case WM_CHARTOITEM:
+ case WM_VKEYTOITEM:
+ case WM_HSCROLL:
+ case WM_VSCROLL:
+ case WM_PARENTNOTIFY:
+ return MessageReflect(m_hWnd, uMsg, wParam, lParam);
+
+ } // switch(uMsg)
+ return FALSE;
+
+ } // INT_PTR CALLBACK CDialog::DialogProc(...)
+
+ inline INT_PTR CDialog::DoModal()
+ {
+ // Create a modal dialog
+ // A modal dialog box must be closed by the user before the application continues
+
+ assert( GetApp() ); // Test if Win32++ has been started
+ assert(!::IsWindow(m_hWnd)); // Only one window per CWnd instance allowed
+
+ INT_PTR nResult = 0;
+
+ try
+ {
+ m_IsModal=TRUE;
+
+ // Ensure this thread has the TLS index set
+ TLSData* pTLSData = GetApp()->SetTlsIndex();
+
+ #ifndef _WIN32_WCE
+ BOOL IsHookedHere = FALSE;
+ if (NULL == pTLSData->hHook )
+ {
+ pTLSData->hHook = ::SetWindowsHookEx(WH_MSGFILTER, (HOOKPROC)StaticMsgHook, NULL, ::GetCurrentThreadId());
+ IsHookedHere = TRUE;
+ }
+ #endif
+
+ HINSTANCE hInstance = GetApp()->GetInstanceHandle();
+ pTLSData->pCWnd = this;
+
+ // Create a modal dialog
+ if (IsIndirect())
+ nResult = ::DialogBoxIndirect(hInstance, m_lpTemplate, m_hParent, (DLGPROC)CDialog::StaticDialogProc);
+ else
+ {
+ if (::FindResource(GetApp()->GetResourceHandle(), m_lpszResName, RT_DIALOG))
+ hInstance = GetApp()->GetResourceHandle();
+ nResult = ::DialogBox(hInstance, m_lpszResName, m_hParent, (DLGPROC)CDialog::StaticDialogProc);
+ }
+
+ // Tidy up
+ m_hWnd = NULL;
+ pTLSData->pCWnd = NULL;
+ GetApp()->CleanupTemps();
+
+ #ifndef _WIN32_WCE
+ if (IsHookedHere)
+ {
+ ::UnhookWindowsHookEx(pTLSData->hHook);
+ pTLSData->hHook = NULL;
+ }
+ #endif
+
+ if (nResult == -1)
+ throw CWinException(_T("Failed to create modal dialog box"));
+
+ }
+
+ catch (const CWinException &e)
+ {
+ TRACE(_T("\n*** Failed to create dialog ***\n"));
+ e.what(); // Display the last error message.
+
+ // eat the exception (don't rethrow)
+ }
+
+ return nResult;
+ }
+
+ inline HWND CDialog::DoModeless()
+ {
+ assert( GetApp() ); // Test if Win32++ has been started
+ assert(!::IsWindow(m_hWnd)); // Only one window per CWnd instance allowed
+
+ try
+ {
+ m_IsModal=FALSE;
+
+ // Ensure this thread has the TLS index set
+ TLSData* pTLSData = GetApp()->SetTlsIndex();
+
+ // Store the CWnd pointer in Thread Local Storage
+ pTLSData->pCWnd = this;
+
+ HINSTANCE hInstance = GetApp()->GetInstanceHandle();
+
+ // Create a modeless dialog
+ if (IsIndirect())
+ m_hWnd = ::CreateDialogIndirect(hInstance, m_lpTemplate, m_hParent, (DLGPROC)CDialog::StaticDialogProc);
+ else
+ {
+ if (::FindResource(GetApp()->GetResourceHandle(), m_lpszResName, RT_DIALOG))
+ hInstance = GetApp()->GetResourceHandle();
+
+ m_hWnd = ::CreateDialog(hInstance, m_lpszResName, m_hParent, (DLGPROC)CDialog::StaticDialogProc);
+ }
+
+ // Tidy up
+ pTLSData->pCWnd = NULL;
+
+ // Now handle dialog creation failure
+ if (!m_hWnd)
+ throw CWinException(_T("Failed to create dialog"));
+ }
+
+ catch (const CWinException &e)
+ {
+ TRACE(_T("\n*** Failed to create dialog ***\n"));
+ e.what(); // Display the last error message.
+
+ // eat the exception (don't rethrow)
+ }
+
+ return m_hWnd;
+ }
+
+ inline void CDialog::EndDialog(INT_PTR nResult)
+ {
+ assert(::IsWindow(m_hWnd));
+
+ if (IsModal())
+ ::EndDialog(m_hWnd, nResult);
+ else
+ Destroy();
+
+ m_hWnd = NULL;
+ }
+
+ inline void CDialog::OnCancel()
+ {
+ // Override to customize OnCancel behaviour
+ EndDialog(IDCANCEL);
+ }
+
+ inline BOOL CDialog::OnInitDialog()
+ {
+ // Called when the dialog is initialized
+ // Override it in your derived class to automatically perform tasks
+ // The return value is used by WM_INITDIALOG
+
+ return TRUE;
+ }
+
+ inline void CDialog::OnOK()
+ {
+ // Override to customize OnOK behaviour
+ EndDialog(IDOK);
+ }
+
+ inline BOOL CDialog::PreTranslateMessage(MSG* pMsg)
+ {
+ // allow the dialog to translate keyboard input
+ if ((pMsg->message >= WM_KEYFIRST) && (pMsg->message <= WM_KEYLAST))
+ {
+ // Process dialog keystrokes for modeless dialogs
+ if (!IsModal())
+ {
+ TLSData* pTLSData = (TLSData*)TlsGetValue(GetApp()->GetTlsIndex());
+ if (NULL == pTLSData->hHook)
+ {
+ if (IsDialogMessage(pMsg))
+ return TRUE;
+ }
+ else
+ {
+ // A modal message loop is running so we can't do IsDialogMessage.
+ // Avoid having modal dialogs create other windows, because those
+ // windows will then use the modal dialog's special message loop.
+ }
+ }
+ }
+
+ return FALSE;
+ }
+
+ inline void CDialog::SetDlgParent(CWnd* pParent)
+ // Allows the parent of the dialog to be set before the dialog is created
+ {
+ m_hParent = pParent? pParent->GetHwnd() : NULL;
+ }
+
+ inline INT_PTR CALLBACK CDialog::StaticDialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+ {
+ // Find the CWnd pointer mapped to this HWND
+ CDialog* w = (CDialog*)GetApp()->GetCWndFromMap(hWnd);
+ if (0 == w)
+ {
+ // The HWND wasn't in the map, so add it now
+ TLSData* pTLSData = (TLSData*)TlsGetValue(GetApp()->GetTlsIndex());
+ assert(pTLSData);
+
+ // Retrieve pointer to CWnd object from Thread Local Storage TLS
+ w = (CDialog*)pTLSData->pCWnd;
+ assert(w);
+ pTLSData->pCWnd = NULL;
+
+ // Store the Window pointer into the HWND map
+ w->m_hWnd = hWnd;
+ w->AddToMap();
+ }
+
+ return w->DialogProc(uMsg, wParam, lParam);
+
+ } // INT_PTR CALLBACK CDialog::StaticDialogProc(...)
+
+#ifndef _WIN32_WCE
+ inline LRESULT CALLBACK CDialog::StaticMsgHook(int nCode, WPARAM wParam, LPARAM lParam)
+ {
+ // Used by Modal Dialogs to PreTranslate Messages
+ TLSData* pTLSData = (TLSData*)TlsGetValue(GetApp()->GetTlsIndex());
+
+ if (nCode == MSGF_DIALOGBOX)
+ {
+ MSG* lpMsg = (MSG*) lParam;
+
+ // only pre-translate keyboard events
+ if ((lpMsg->message >= WM_KEYFIRST && lpMsg->message <= WM_KEYLAST))
+ {
+ for (HWND hWnd = lpMsg->hwnd; hWnd != NULL; hWnd = ::GetParent(hWnd))
+ {
+ CDialog* pDialog = (CDialog*)GetApp()->GetCWndFromMap(hWnd);
+ if (pDialog && (lstrcmp(pDialog->GetClassName(), _T("#32770")) == 0)) // only for dialogs
+ {
+ pDialog->PreTranslateMessage(lpMsg);
+ break;
+ }
+ }
+ }
+ }
+
+ return ::CallNextHookEx(pTLSData->hHook, nCode, wParam, lParam);
+ }
+#endif
+
+
+
+#ifndef _WIN32_WCE
+
+ /////////////////////////////////////
+ // Definitions for the CResizer class
+ //
+
+ void inline CResizer::AddChild(CWnd* pWnd, Alignment corner, DWORD dwStyle)
+ // Adds a child window (usually a dialog control) to the set of windows managed by
+ // the Resizer.
+ //
+ // The alignment corner should be set to the closest corner of the dialog. Allowed
+ // values are topleft, topright, bottomleft, and bottomright.
+ // Set bFixedWidth to TRUE if the width should be fixed instead of variable.
+ // Set bFixedHeight to TRUE if the height should be fixed instead of variable.
+ {
+ ResizeData rd;
+ rd.corner = corner;
+ rd.bFixedWidth = !(dwStyle & RD_STRETCH_WIDTH);
+ rd.bFixedHeight = !(dwStyle & RD_STRETCH_HEIGHT);
+ CRect rcInit = pWnd->GetWindowRect();
+ m_pParent->ScreenToClient(rcInit);
+ rd.rcInit = rcInit;
+ rd.hWnd = pWnd->GetHwnd();
+
+ m_vResizeData.insert(m_vResizeData.begin(), rd);
+ }
+
+ void inline CResizer::AddChild(HWND hWnd, Alignment corner, DWORD dwStyle)
+ // Adds a child window (usually a dialog control) to the set of windows managed by
+ // the Resizer.
+ {
+ AddChild(FromHandle(hWnd), corner, dwStyle);
+ }
+
+ inline void CResizer::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
+ {
+ switch (uMsg)
+ {
+ case WM_SIZE:
+ RecalcLayout();
+ break;
+
+ case WM_HSCROLL:
+ if (0 == lParam)
+ OnHScroll(wParam, lParam);
+ break;
+
+ case WM_VSCROLL:
+ if (0 == lParam)
+ OnVScroll(wParam, lParam);
+ break;
+ }
+ }
+
+ void inline CResizer::Initialize(CWnd* pParent, RECT rcMin, RECT rcMax)
+ // Sets up the Resizer by specifying the parent window (usually a dialog),
+ // and the minimum and maximum allowed rectangle sizes.
+ {
+ assert (NULL != pParent);
+
+ m_pParent = pParent;
+ m_rcInit = pParent->GetClientRect();
+ m_rcMin = rcMin;
+ m_rcMax = rcMax;
+
+ // Add scroll bar support to the parent window
+ DWORD dwStyle = (DWORD)m_pParent->GetClassLongPtr(GCL_STYLE);
+ dwStyle |= WS_HSCROLL | WS_VSCROLL;
+ m_pParent->SetClassLongPtr(GCL_STYLE, dwStyle);
+ }
+
+ void inline CResizer::OnHScroll(WPARAM wParam, LPARAM /*lParam*/)
+ {
+ int xNewPos;
+
+ switch (LOWORD(wParam))
+ {
+ case SB_PAGEUP: // User clicked the scroll bar shaft left of the scroll box.
+ xNewPos = m_xScrollPos - 50;
+ break;
+
+ case SB_PAGEDOWN: // User clicked the scroll bar shaft right of the scroll box.
+ xNewPos = m_xScrollPos + 50;
+ break;
+
+ case SB_LINEUP: // User clicked the left arrow.
+ xNewPos = m_xScrollPos - 5;
+ break;
+
+ case SB_LINEDOWN: // User clicked the right arrow.
+ xNewPos = m_xScrollPos + 5;
+ break;
+
+ case SB_THUMBPOSITION: // User dragged the scroll box.
+ xNewPos = HIWORD(wParam);
+ break;
+
+ case SB_THUMBTRACK: // User dragging the scroll box.
+ xNewPos = HIWORD(wParam);
+ break;
+
+ default:
+ xNewPos = m_xScrollPos;
+ }
+
+ // Scroll the window.
+ xNewPos = MAX(0, xNewPos);
+ xNewPos = MIN( xNewPos, GetMinRect().Width() - m_pParent->GetClientRect().Width() );
+ int xDelta = xNewPos - m_xScrollPos;
+ m_xScrollPos = xNewPos;
+ m_pParent->ScrollWindow(-xDelta, 0, NULL, NULL);
+
+ // Reset the scroll bar.
+ SCROLLINFO si = {0};
+ si.cbSize = sizeof(si);
+ si.fMask = SIF_POS;
+ si.nPos = m_xScrollPos;
+ m_pParent->SetScrollInfo(SB_HORZ, si, TRUE);
+ }
+
+ void inline CResizer::OnVScroll(WPARAM wParam, LPARAM /*lParam*/)
+ {
+ int yNewPos;
+
+ switch (LOWORD(wParam))
+ {
+ case SB_PAGEUP: // User clicked the scroll bar shaft above the scroll box.
+ yNewPos = m_yScrollPos - 50;
+ break;
+
+ case SB_PAGEDOWN: // User clicked the scroll bar shaft below the scroll box.
+ yNewPos = m_yScrollPos + 50;
+ break;
+
+ case SB_LINEUP: // User clicked the top arrow.
+ yNewPos = m_yScrollPos - 5;
+ break;
+
+ case SB_LINEDOWN: // User clicked the bottom arrow.
+ yNewPos = m_yScrollPos + 5;
+ break;
+
+ case SB_THUMBPOSITION: // User dragged the scroll box.
+ yNewPos = HIWORD(wParam);
+ break;
+
+ case SB_THUMBTRACK: // User dragging the scroll box.
+ yNewPos = HIWORD(wParam);
+ break;
+
+ default:
+ yNewPos = m_yScrollPos;
+ }
+
+ // Scroll the window.
+ yNewPos = MAX(0, yNewPos);
+ yNewPos = MIN( yNewPos, GetMinRect().Height() - m_pParent->GetClientRect().Height() );
+ int yDelta = yNewPos - m_yScrollPos;
+ m_yScrollPos = yNewPos;
+ m_pParent->ScrollWindow(0, -yDelta, NULL, NULL);
+
+ // Reset the scroll bar.
+ SCROLLINFO si = {0};
+ si.cbSize = sizeof(si);
+ si.fMask = SIF_POS;
+ si.nPos = m_yScrollPos;
+ m_pParent->SetScrollInfo(SB_VERT, si, TRUE);
+ }
+
+ void inline CResizer::RecalcLayout()
+ // Repositions the child windows. Call this function when handling
+ // the WM_SIZE message in the parent window.
+ {
+ assert (m_rcInit.Width() > 0 && m_rcInit.Height() > 0);
+ assert (NULL != m_pParent);
+
+ CRect rcCurrent = m_pParent->GetClientRect();
+
+ // Adjust the scrolling if required
+ m_xScrollPos = MIN(m_xScrollPos, MAX(0, m_rcMin.Width() - rcCurrent.Width() ) );
+ m_yScrollPos = MIN(m_yScrollPos, MAX(0, m_rcMin.Height() - rcCurrent.Height()) );
+ SCROLLINFO si = {0};
+ si.cbSize = sizeof(si);
+ si.fMask = SIF_RANGE | SIF_PAGE | SIF_POS;
+ si.nMax = m_rcMin.Width();
+ si.nPage = rcCurrent.Width();
+ si.nPos = m_xScrollPos;
+ m_pParent->SetScrollInfo(SB_HORZ, si, TRUE);
+ si.nMax = m_rcMin.Height();
+ si.nPage = rcCurrent.Height();
+ si.nPos = m_yScrollPos;
+ m_pParent->SetScrollInfo(SB_VERT, si, TRUE);
+
+ rcCurrent.right = MAX( rcCurrent.Width(), m_rcMin.Width() );
+ rcCurrent.bottom = MAX( rcCurrent.Height(), m_rcMin.Height() );
+ if (!m_rcMax.IsRectEmpty())
+ {
+ rcCurrent.right = MIN( rcCurrent.Width(), m_rcMax.Width() );
+ rcCurrent.bottom = MIN( rcCurrent.Height(), m_rcMax.Height() );
+ }
+
+ // Declare an iterator to step through the vector
+ std::vector<ResizeData>::iterator iter;
+
+ for (iter = m_vResizeData.begin(); iter < m_vResizeData.end(); ++iter)
+ {
+ int left = 0;
+ int top = 0;
+ int width = 0;
+ int height = 0;
+
+ // Calculate the new size and position of the child window
+ switch( (*iter).corner )
+ {
+ case topleft:
+ width = (*iter).bFixedWidth? (*iter).rcInit.Width() : (*iter).rcInit.Width() - m_rcInit.Width() + rcCurrent.Width();
+ height = (*iter).bFixedHeight? (*iter).rcInit.Height() : (*iter).rcInit.Height() - m_rcInit.Height() + rcCurrent.Height();
+ left = (*iter).rcInit.left;
+ top = (*iter).rcInit.top;
+ break;
+ case topright:
+ width = (*iter).bFixedWidth? (*iter).rcInit.Width() : (*iter).rcInit.Width() - m_rcInit.Width() + rcCurrent.Width();
+ height = (*iter).bFixedHeight? (*iter).rcInit.Height() : (*iter).rcInit.Height() - m_rcInit.Height() + rcCurrent.Height();
+ left = (*iter).rcInit.right - width - m_rcInit.Width() + rcCurrent.Width();
+ top = (*iter).rcInit.top;
+ break;
+ case bottomleft:
+ width = (*iter).bFixedWidth? (*iter).rcInit.Width() : (*iter).rcInit.Width() - m_rcInit.Width() + rcCurrent.Width();
+ height = (*iter).bFixedHeight? (*iter).rcInit.Height() : (*iter).rcInit.Height() - m_rcInit.Height() + rcCurrent.Height();
+ left = (*iter).rcInit.left;
+ top = (*iter).rcInit.bottom - height - m_rcInit.Height() + rcCurrent.Height();
+ break;
+ case bottomright:
+ width = (*iter).bFixedWidth? (*iter).rcInit.Width() : (*iter).rcInit.Width() - m_rcInit.Width() + rcCurrent.Width();
+ height = (*iter).bFixedHeight? (*iter).rcInit.Height() : (*iter).rcInit.Height() - m_rcInit.Height() + rcCurrent.Height();
+ left = (*iter).rcInit.right - width - m_rcInit.Width() + rcCurrent.Width();
+ top = (*iter).rcInit.bottom - height - m_rcInit.Height() + rcCurrent.Height();
+ break;
+ }
+
+ // Position the child window.
+ CRect rc(left - m_xScrollPos, top - m_yScrollPos, left + width - m_xScrollPos, top + height - m_yScrollPos);
+ if ( rc != (*iter).rcOld)
+ {
+ CWnd* pWnd = FromHandle((*iter).hWnd);
+ CWnd *pWndPrev = pWnd->GetWindow(GW_HWNDPREV); // Trick to maintain the original tab order.
+ HWND hWnd = pWndPrev ? pWndPrev->GetHwnd():NULL;
+ pWnd->SetWindowPos(hWnd, rc, SWP_NOCOPYBITS);
+ (*iter).rcOld = rc;
+ }
+ }
+ }
+
+#endif // #ifndef _WIN32_WCE
+
+} // namespace Win32xx
+
+
+
+#endif // _WIN32XX_DIALOG_H_
+
diff --git a/mmc_updater/depends/win32cpp/docking.h b/mmc_updater/depends/win32cpp/docking.h
new file mode 100644
index 00000000..9e7c4486
--- /dev/null
+++ b/mmc_updater/depends/win32cpp/docking.h
@@ -0,0 +1,4214 @@
+// Win32++ Version 7.2
+// Released: 5th AUgust 2011
+//
+// David Nash
+// email: dnash@bigpond.net.au
+// url: https://sourceforge.net/projects/win32-framework
+//
+//
+// Copyright (c) 2005-2011 David Nash
+//
+// Permission is hereby granted, free of charge, to
+// any person obtaining a copy of this software and
+// associated documentation files (the "Software"),
+// to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify,
+// merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom
+// the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice
+// shall be included in all copies or substantial portions
+// of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
+// OR OTHER DEALINGS IN THE SOFTWARE.
+//
+////////////////////////////////////////////////////////
+
+
+///////////////////////////////////////////////////////
+// docking.h
+// Declaration of the CDocker class
+
+#ifndef _WIN32XX_DOCKING_H_
+#define _WIN32XX_DOCKING_H_
+
+
+#include "wincore.h"
+#include "gdi.h"
+#include "toolbar.h"
+#include "tab.h"
+#include "frame.h"
+#include "default_resource.h"
+
+
+// Docking Styles
+#define DS_DOCKED_LEFT 0x0001 // Dock the child left
+#define DS_DOCKED_RIGHT 0x0002 // Dock the child right
+#define DS_DOCKED_TOP 0x0004 // Dock the child top
+#define DS_DOCKED_BOTTOM 0x0008 // Dock the child bottom
+#define DS_NO_DOCKCHILD_LEFT 0x0010 // Prevent a child docking left
+#define DS_NO_DOCKCHILD_RIGHT 0x0020 // Prevent a child docking right
+#define DS_NO_DOCKCHILD_TOP 0x0040 // Prevent a child docking at the top
+#define DS_NO_DOCKCHILD_BOTTOM 0x0080 // Prevent a child docking at the bottom
+#define DS_NO_RESIZE 0x0100 // Prevent resizing
+#define DS_NO_CAPTION 0x0200 // Prevent display of caption when docked
+#define DS_NO_CLOSE 0x0400 // Prevent closing of a docker while docked
+#define DS_NO_UNDOCK 0x0800 // Prevent undocking and dock closing
+#define DS_CLIENTEDGE 0x1000 // Has a 3D border when docked
+#define DS_FIXED_RESIZE 0x2000 // Perfomed a fixed resize instead of a proportional resize on dock children
+#define DS_DOCKED_CONTAINER 0x4000 // Dock a container within a container
+#define DS_DOCKED_LEFTMOST 0x10000 // Leftmost outer docking
+#define DS_DOCKED_RIGHTMOST 0x20000 // Rightmost outer docking
+#define DS_DOCKED_TOPMOST 0x40000 // Topmost outer docking
+#define DS_DOCKED_BOTTOMMOST 0x80000 // Bottommost outer docking
+
+// Required for Dev-C++
+#ifndef TME_NONCLIENT
+ #define TME_NONCLIENT 0x00000010
+#endif
+#ifndef TME_LEAVE
+ #define TME_LEAVE 0x000000002
+#endif
+#ifndef WM_NCMOUSELEAVE
+ #define WM_NCMOUSELEAVE 0x000002A2
+#endif
+
+namespace Win32xx
+{
+ // Class declarations
+ class CDockContainer;
+ class CDocker;
+
+ typedef Shared_Ptr<CDocker> DockPtr;
+
+ struct ContainerInfo
+ {
+ TCHAR szTitle[MAX_MENU_STRING];
+ int iImage;
+ CDockContainer* pContainer;
+ };
+
+ ///////////////////////////////////////
+ // Declaration of the CDockContainer class
+ // A CDockContainer is a CTab window. A CTab has a view window, and optionally a toolbar control.
+ // A top level CDockContainer can contain other CDockContainers. The view for each container
+ // (including the top level container) along with possibly its toolbar, is displayed
+ // within the container parent's view page.
+ class CDockContainer : public CTab
+ {
+ public:
+
+ // Nested class. This is the Wnd for the window displayed over the client area
+ // of the tab control. The toolbar and view window are child windows of the
+ // viewpage window. Only the ViewPage of the parent CDockContainer is displayed. It's
+ // contents are updated with the view window of the relevant container whenever
+ // a different tab is selected.
+ class CViewPage : public CWnd
+ {
+
+ public:
+ CViewPage() : m_pView(NULL), m_pTab(NULL) {}
+ virtual ~CViewPage() {}
+ virtual CToolBar& GetToolBar() const {return (CToolBar&)m_ToolBar;}
+ virtual CWnd* GetView() const {return m_pView;}
+ virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam);
+ virtual void OnCreate();
+ virtual LRESULT OnNotify(WPARAM wParam, LPARAM lParam);
+ virtual void PreRegisterClass(WNDCLASS &wc);
+ virtual void RecalcLayout();
+ virtual void SetView(CWnd& wndView);
+ virtual LRESULT WndProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam);
+
+ CWnd* GetTabCtrl() const { return m_pTab;}
+
+ private:
+ CToolBar m_ToolBar;
+ tString m_tsTooltip;
+ CWnd* m_pView;
+ CWnd* m_pTab;
+ };
+
+ public:
+ CDockContainer();
+ virtual ~CDockContainer();
+ virtual void AddContainer(CDockContainer* pContainer);
+ virtual void AddToolBarButton(UINT nID, BOOL bEnabled = TRUE);
+ virtual CDockContainer* GetContainerFromIndex(UINT nPage);
+ virtual CDockContainer* GetContainerFromView(CWnd* pView) const;
+ virtual int GetContainerIndex(CDockContainer* pContainer);
+ virtual SIZE GetMaxTabTextSize();
+ virtual CViewPage& GetViewPage() const { return (CViewPage&)m_ViewPage; }
+ virtual void RecalcLayout();
+ virtual void RemoveContainer(CDockContainer* pWnd);
+ virtual void SelectPage(int nPage);
+ virtual void SetTabSize();
+ virtual void SetupToolBar();
+
+ // Attributes
+ CDockContainer* GetActiveContainer() const {return GetContainerFromView(GetActiveView());}
+ CWnd* GetActiveView() const;
+ std::vector<ContainerInfo>& GetAllContainers() const {return m_pContainerParent->m_vContainerInfo;}
+ CDockContainer* GetContainerParent() const { return m_pContainerParent; }
+ CString& GetDockCaption() const { return (CString&)m_csCaption; }
+ HICON GetTabIcon() const { return m_hTabIcon; }
+ LPCTSTR GetTabText() const { return m_tsTabText.c_str(); }
+ virtual CToolBar& GetToolBar() const { return GetViewPage().GetToolBar(); }
+ CWnd* GetView() const { return GetViewPage().GetView(); }
+ void SetActiveContainer(CDockContainer* pContainer);
+ void SetDockCaption(LPCTSTR szCaption) { m_csCaption = szCaption; }
+ void SetTabIcon(HICON hTabIcon) { m_hTabIcon = hTabIcon; }
+ void SetTabIcon(UINT nID_Icon);
+ void SetTabIcon(int i, HICON hIcon) { CTab::SetTabIcon(i, hIcon); }
+ void SetTabText(LPCTSTR szText) { m_tsTabText = szText; }
+ void SetTabText(UINT nTab, LPCTSTR szText);
+ void SetView(CWnd& Wnd);
+
+ protected:
+ virtual void OnCreate();
+ virtual void OnLButtonDown(WPARAM wParam, LPARAM lParam);
+ virtual void OnLButtonUp(WPARAM wParam, LPARAM lParam);
+ virtual void OnMouseLeave(WPARAM wParam, LPARAM lParam);
+ virtual LRESULT OnNotifyReflect(WPARAM wParam, LPARAM lParam);
+ virtual void PreCreate(CREATESTRUCT &cs);
+ virtual LRESULT WndProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam);
+
+ private:
+ std::vector<ContainerInfo> m_vContainerInfo;
+ tString m_tsTabText;
+ CString m_csCaption;
+ CViewPage m_ViewPage;
+ int m_iCurrentPage;
+ CDockContainer* m_pContainerParent;
+ HICON m_hTabIcon;
+ int m_nTabPressed;
+
+ };
+
+ typedef struct DRAGPOS
+ {
+ NMHDR hdr;
+ POINT ptPos;
+ UINT DockZone;
+ } *LPDRAGPOS;
+
+
+ /////////////////////////////////////////
+ // Declaration of the CDocker class
+ // A CDocker window allows other CDocker windows to be "docked" inside it.
+ // A CDocker can dock on the top, left, right or bottom side of a parent CDocker.
+ // There is no theoretical limit to the number of CDockers within CDockers.
+ class CDocker : public CWnd
+ {
+ public:
+ // A nested class for the splitter bar that seperates the docked panes.
+ class CDockBar : public CWnd
+ {
+ public:
+ CDockBar();
+ virtual ~CDockBar();
+ virtual void OnDraw(CDC* pDC);
+ virtual void PreCreate(CREATESTRUCT &cs);
+ virtual void PreRegisterClass(WNDCLASS& wc);
+ virtual void SendNotify(UINT nMessageID);
+ virtual void SetColor(COLORREF color);
+ virtual LRESULT WndProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam);
+
+ CDocker* GetDock() {return m_pDock;}
+ int GetWidth() {return m_DockBarWidth;}
+ void SetDock(CDocker* pDock) {m_pDock = pDock;}
+ void SetWidth(int nWidth) {m_DockBarWidth = nWidth;}
+
+ private:
+ CDockBar(const CDockBar&); // Disable copy construction
+ CDockBar& operator = (const CDockBar&); // Disable assignment operator
+
+ CDocker* m_pDock;
+ DRAGPOS m_DragPos;
+ CBrush m_brBackground;
+ int m_DockBarWidth;
+ };
+
+ // A nested class for the window inside a CDocker which includes all of this docked client.
+ // It's the remaining part of the CDocker that doesn't belong to the CDocker's children.
+ // The Docker's view window is a child window of CDockClient.
+ class CDockClient : public CWnd
+ {
+ public:
+ CDockClient();
+ virtual ~CDockClient() {}
+ virtual void Draw3DBorder(RECT& Rect);
+ virtual void DrawCaption(WPARAM wParam);
+ virtual void DrawCloseButton(CDC& DrawDC, BOOL bFocus);
+ virtual CRect GetCloseRect();
+ virtual void SendNotify(UINT nMessageID);
+
+ CString& GetCaption() const { return (CString&)m_csCaption; }
+ CWnd* GetView() const { return m_pView; }
+ void SetDock(CDocker* pDock) { m_pDock = pDock;}
+ void SetCaption(LPCTSTR szCaption) { m_csCaption = szCaption; }
+ void SetCaptionColors(COLORREF Foregnd1, COLORREF Backgnd1, COLORREF ForeGnd2, COLORREF BackGnd2);
+ void SetClosePressed() { m_IsClosePressed = TRUE; }
+ void SetView(CWnd& Wnd) { m_pView = &Wnd; }
+
+ protected:
+ virtual void OnLButtonDown(WPARAM wParam, LPARAM lParam);
+ virtual void OnLButtonUp(WPARAM wParam, LPARAM lParam);
+ virtual void OnMouseActivate(WPARAM wParam, LPARAM lParam);
+ virtual void OnMouseMove(WPARAM wParam, LPARAM lParam);
+ virtual void OnNCCalcSize(WPARAM& wParam, LPARAM& lParam);
+ virtual LRESULT OnNCHitTest(WPARAM wParam, LPARAM lParam);
+ virtual LRESULT OnNCLButtonDown(WPARAM wParam, LPARAM lParam);
+ virtual void OnNCMouseLeave(WPARAM wParam, LPARAM lParam);
+ virtual LRESULT OnNCMouseMove(WPARAM wParam, LPARAM lParam);
+ virtual LRESULT OnNCPaint(WPARAM wParam, LPARAM lParam);
+ virtual void OnWindowPosChanged(WPARAM wParam, LPARAM lParam);
+ virtual void PreRegisterClass(WNDCLASS& wc);
+ virtual void PreCreate(CREATESTRUCT& cs);
+ virtual LRESULT WndProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam);
+
+ private:
+ CDockClient(const CDockClient&); // Disable copy construction
+ CDockClient& operator = (const CDockClient&); // Disable assignment operator
+
+ CString m_csCaption;
+ CPoint m_Oldpt;
+ CDocker* m_pDock;
+ CWnd* m_pView;
+ BOOL m_IsClosePressed;
+ BOOL m_bOldFocus;
+ BOOL m_bCaptionPressed;
+ BOOL m_IsTracking;
+ COLORREF m_Foregnd1;
+ COLORREF m_Backgnd1;
+ COLORREF m_Foregnd2;
+ COLORREF m_Backgnd2;
+ };
+
+ // This nested class is used to indicate where a window could dock by
+ // displaying a blue tinted window.
+ class CDockHint : public CWnd
+ {
+ public:
+ CDockHint();
+ virtual ~CDockHint();
+ virtual RECT CalcHintRectContainer(CDocker* pDockTarget);
+ virtual RECT CalcHintRectInner(CDocker* pDockTarget, CDocker* pDockDrag, UINT uDockSide);
+ virtual RECT CalcHintRectOuter(CDocker* pDockDrag, UINT uDockSide);
+ virtual void DisplayHint(CDocker* pDockTarget, CDocker* pDockDrag, UINT uDockSide);
+ virtual void OnDraw(CDC* pDC);
+ virtual void PreCreate(CREATESTRUCT &cs);
+ virtual void ShowHintWindow(CDocker* pDockTarget, CRect rcHint);
+
+ private:
+ CDockHint(const CDockHint&); // Disable copy construction
+ CDockHint& operator = (const CDockHint&); // Disable assignment operator
+
+ CBitmap m_bmBlueTint;
+ UINT m_uDockSideOld;
+ };
+
+ class CTarget : public CWnd
+ {
+ public:
+ CTarget() {}
+ virtual ~CTarget();
+ virtual void OnDraw(CDC* pDC);
+ virtual void PreCreate(CREATESTRUCT &cs);
+
+ protected:
+ CBitmap m_bmImage;
+
+ private:
+ CTarget(const CTarget&); // Disable copy construction
+ CTarget& operator = (const CTarget&); // Disable assignment operator
+ };
+
+ class CTargetCentre : public CTarget
+ {
+ public:
+ CTargetCentre();
+ virtual ~CTargetCentre();
+ virtual void OnDraw(CDC* pDC);
+ virtual void OnCreate();
+ virtual BOOL CheckTarget(LPDRAGPOS pDragPos);
+ BOOL IsOverContainer() { return m_bIsOverContainer; }
+
+ private:
+ CTargetCentre(const CTargetCentre&); // Disable copy construction
+ CTargetCentre& operator = (const CTargetCentre&); // Disable assignment operator
+
+ BOOL m_bIsOverContainer;
+ CDocker* m_pOldDockTarget;
+ };
+
+ class CTargetLeft : public CTarget
+ {
+ public:
+ CTargetLeft() {m_bmImage.LoadImage(IDW_SDLEFT,0,0,0);}
+ virtual BOOL CheckTarget(LPDRAGPOS pDragPos);
+
+ private:
+ CTargetLeft(const CTargetLeft&); // Disable copy construction
+ CTargetLeft& operator = (const CTargetLeft&); // Disable assignment operator
+ };
+
+ class CTargetTop : public CTarget
+ {
+ public:
+ CTargetTop() {m_bmImage.LoadImage(IDW_SDTOP,0,0,0);}
+ virtual BOOL CheckTarget(LPDRAGPOS pDragPos);
+ private:
+ CTargetTop(const CTargetTop&); // Disable copy construction
+ CTargetTop& operator = (const CTargetTop&); // Disable assignment operator
+ };
+
+ class CTargetRight : public CTarget
+ {
+ public:
+ CTargetRight() {m_bmImage.LoadImage(IDW_SDRIGHT,0,0,0);}
+ virtual BOOL CheckTarget(LPDRAGPOS pDragPos);
+
+ private:
+ CTargetRight(const CTargetRight&); // Disable copy construction
+ CTargetRight& operator = (const CTargetRight&); // Disable assignment operator
+ };
+
+ class CTargetBottom : public CTarget
+ {
+ public:
+ CTargetBottom() {m_bmImage.LoadImage(IDW_SDBOTTOM,0,0,0);}
+ virtual BOOL CheckTarget(LPDRAGPOS pDragPos);
+ };
+
+ friend class CTargetCentre;
+ friend class CTargetLeft;
+ friend class CTargetTop;
+ friend class CTargetRight;
+ friend class CTargetBottom;
+ friend class CDockClient;
+ friend class CDockContainer;
+
+ public:
+ // Operations
+ CDocker();
+ virtual ~CDocker();
+ virtual CDocker* AddDockedChild(CDocker* pDocker, DWORD dwDockStyle, int DockSize, int nDockID = 0);
+ virtual CDocker* AddUndockedChild(CDocker* pDocker, DWORD dwDockStyle, int DockSize, RECT rc, int nDockID = 0);
+ virtual void Close();
+ virtual void CloseAllDockers();
+ virtual void Dock(CDocker* pDocker, UINT uDockSide);
+ virtual void DockInContainer(CDocker* pDock, DWORD dwDockStyle);
+ virtual CDockContainer* GetContainer() const;
+ virtual CDocker* GetActiveDocker() const;
+ virtual CDocker* GetDockAncestor() const;
+ virtual CDocker* GetDockFromID(int n_DockID) const;
+ virtual CDocker* GetDockFromPoint(POINT pt) const;
+ virtual CDocker* GetDockFromView(CWnd* pView) const;
+ virtual CDocker* GetTopmostDocker() const;
+ virtual int GetDockSize() const;
+ virtual CTabbedMDI* GetTabbedMDI() const;
+ virtual int GetTextHeight();
+ virtual void Hide();
+ virtual BOOL LoadRegistrySettings(tString tsRegistryKeyName);
+ virtual void RecalcDockLayout();
+ virtual BOOL SaveRegistrySettings(tString tsRegistryKeyName);
+ virtual void Undock(CPoint pt, BOOL bShowUndocked = TRUE);
+ virtual void UndockContainer(CDockContainer* pContainer, CPoint pt, BOOL bShowUndocked);
+ virtual BOOL VerifyDockers();
+
+ // Attributes
+ virtual CDockBar& GetDockBar() const {return (CDockBar&)m_DockBar;}
+ virtual CDockClient& GetDockClient() const {return (CDockClient&)m_DockClient;}
+ virtual CDockHint& GetDockHint() const {return m_pDockAncestor->m_DockHint;}
+
+
+ std::vector <DockPtr> & GetAllDockers() const {return GetDockAncestor()->m_vAllDockers;}
+ int GetBarWidth() const {return GetDockBar().GetWidth();}
+ CString& GetCaption() const {return GetDockClient().GetCaption();}
+ std::vector <CDocker*> & GetDockChildren() const {return (std::vector <CDocker*> &)m_vDockChildren;}
+ int GetDockID() const {return m_nDockID;}
+ CDocker* GetDockParent() const {return m_pDockParent;}
+ DWORD GetDockStyle() const {return m_DockStyle;}
+ CWnd* GetView() const {return GetDockClient().GetView();}
+ BOOL IsChildOfDocker(CWnd* pWnd) const;
+ BOOL IsDocked() const;
+ BOOL IsDragAutoResize();
+ BOOL IsRelated(CWnd* pWnd) const;
+ BOOL IsUndocked() const;
+ void SetBarColor(COLORREF color) {GetDockBar().SetColor(color);}
+ void SetBarWidth(int nWidth) {GetDockBar().SetWidth(nWidth);}
+ void SetCaption(LPCTSTR szCaption);
+ void SetCaptionColors(COLORREF Foregnd1, COLORREF Backgnd1, COLORREF ForeGnd2, COLORREF BackGnd2);
+ void SetCaptionHeight(int nHeight);
+ void SetDockStyle(DWORD dwDockStyle);
+ void SetDockSize(int DockSize);
+ void SetDragAutoResize(BOOL bAutoResize);
+ void SetView(CWnd& wndView);
+
+ protected:
+ virtual CDocker* NewDockerFromID(int idDock);
+ virtual void OnActivate(WPARAM wParam, LPARAM lParam);
+ virtual void OnCaptionTimer(WPARAM wParam, LPARAM lParam);
+ virtual void OnCreate();
+ virtual void OnDestroy(WPARAM wParam, LPARAM lParam);
+ virtual void OnDockDestroyed(WPARAM wParam, LPARAM lParam);
+ virtual void OnExitSizeMove(WPARAM wParam, LPARAM lParam);
+ virtual LRESULT OnNotify(WPARAM wParam, LPARAM lParam);
+ virtual void OnSetFocus(WPARAM wParam, LPARAM lParam);
+ virtual void OnSysColorChange(WPARAM wParam, LPARAM lParam);
+ virtual LRESULT OnSysCommand(WPARAM wParam, LPARAM lParam);
+ virtual LRESULT OnWindowPosChanging(WPARAM wParam, LPARAM lParam);
+ virtual void OnWindowPosChanged(WPARAM wParam, LPARAM lParam);
+ virtual void PreCreate(CREATESTRUCT &cs);
+ virtual void PreRegisterClass(WNDCLASS &wc);
+ virtual LRESULT WndProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam);
+
+ private:
+ CDocker(const CDocker&); // Disable copy construction
+ CDocker& operator = (const CDocker&); // Disable assignment operator
+ void CheckAllTargets(LPDRAGPOS pDragPos);
+ void CloseAllTargets();
+ void DockOuter(CDocker* pDocker, DWORD dwDockStyle);
+ void DrawAllCaptions();
+ void DrawHashBar(HWND hBar, POINT Pos);
+ void ConvertToChild(HWND hWndParent);
+ void ConvertToPopup(RECT rc);
+ void MoveDockChildren(CDocker* pDockTarget);
+ void PromoteFirstChild();
+ void RecalcDockChildLayout(CRect rc);
+ void ResizeDockers(LPDRAGPOS pdp);
+ CDocker* SeparateFromDock();
+ void SendNotify(UINT nMessageID);
+ void SetUndockPosition(CPoint pt);
+ std::vector<CDocker*> SortDockers();
+
+ CDockBar m_DockBar;
+ CDockHint m_DockHint;
+ CDockClient m_DockClient;
+ CTargetCentre m_TargetCentre;
+ CTargetLeft m_TargetLeft;
+ CTargetTop m_TargetTop;
+ CTargetRight m_TargetRight;
+ CPoint m_OldPoint;
+ CTargetBottom m_TargetBottom;
+ CDocker* m_pDockParent;
+ CDocker* m_pDockAncestor;
+ CDocker* m_pDockActive;
+
+ std::vector <CDocker*> m_vDockChildren;
+ std::vector <DockPtr> m_vAllDockers; // Only used in DockAncestor
+
+ CRect m_rcBar;
+ CRect m_rcChild;
+
+ BOOL m_BlockMove;
+ BOOL m_Undocking;
+ BOOL m_bIsClosing;
+ BOOL m_bIsDragging;
+ BOOL m_bDragAutoResize;
+ int m_DockStartSize;
+ int m_nDockID;
+ int m_nTimerCount;
+ int m_NCHeight;
+ DWORD m_dwDockZone;
+ double m_DockSizeRatio;
+ DWORD m_DockStyle;
+ HWND m_hOldFocus;
+
+ }; // class CDocker
+
+ struct DockInfo
+ {
+ DWORD DockStyle;
+ int DockSize;
+ int DockID;
+ int DockParentID;
+ RECT Rect;
+ };
+
+}
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+namespace Win32xx
+{
+
+ /////////////////////////////////////////////////////////////
+ // Definitions for the CDockBar class nested within CDocker
+ //
+ inline CDocker::CDockBar::CDockBar() : m_pDock(NULL), m_DockBarWidth(4)
+ {
+ m_brBackground.CreateSolidBrush(RGB(192,192,192));
+ }
+
+ inline CDocker::CDockBar::~CDockBar()
+ {
+ }
+
+ inline void CDocker::CDockBar::OnDraw(CDC* pDC)
+ {
+ CRect rcClient = GetClientRect();
+ pDC->SelectObject(&m_brBackground);
+ pDC->PatBlt(0, 0, rcClient.Width(), rcClient.Height(), PATCOPY);
+ }
+
+ inline void CDocker::CDockBar::PreCreate(CREATESTRUCT &cs)
+ {
+ // Create a child window, initially hidden
+ cs.style = WS_CHILD;
+ }
+
+ inline void CDocker::CDockBar::PreRegisterClass(WNDCLASS& wc)
+ {
+ wc.lpszClassName = _T("Win32++ Bar");
+ wc.hbrBackground = m_brBackground;
+ }
+
+ inline void CDocker::CDockBar::SendNotify(UINT nMessageID)
+ {
+ // Send a splitter bar notification to the parent
+ m_DragPos.hdr.code = nMessageID;
+ m_DragPos.hdr.hwndFrom = m_hWnd;
+ m_DragPos.ptPos = GetCursorPos();
+ m_DragPos.ptPos.x += 1;
+ GetParent()->SendMessage(WM_NOTIFY, 0L, (LPARAM)&m_DragPos);
+ }
+
+ inline void CDocker::CDockBar::SetColor(COLORREF color)
+ {
+ // Useful colors:
+ // GetSysColor(COLOR_BTNFACE) // Default Grey
+ // RGB(196, 215, 250) // Default Blue
+
+ m_brBackground.CreateSolidBrush(color);
+ }
+
+ inline LRESULT CDocker::CDockBar::WndProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam)
+ {
+ {
+ switch (uMsg)
+ {
+ case WM_SETCURSOR:
+ {
+ if (!(m_pDock->GetDockStyle() & DS_NO_RESIZE))
+ {
+ HCURSOR hCursor;
+ DWORD dwSide = GetDock()->GetDockStyle() & 0xF;
+ if ((dwSide == DS_DOCKED_LEFT) || (dwSide == DS_DOCKED_RIGHT))
+ hCursor = LoadCursor(GetApp()->GetResourceHandle(), MAKEINTRESOURCE(IDW_SPLITH));
+ else
+ hCursor = LoadCursor(GetApp()->GetResourceHandle(), MAKEINTRESOURCE(IDW_SPLITV));
+
+ if (hCursor) SetCursor(hCursor);
+ else TRACE(_T("**WARNING** Missing cursor resource for slider bar\n"));
+
+ return TRUE;
+ }
+ else
+ SetCursor(LoadCursor(NULL, IDC_ARROW));
+ }
+ break;
+
+ case WM_ERASEBKGND:
+ return 0;
+
+ case WM_LBUTTONDOWN:
+ {
+ if (!(m_pDock->GetDockStyle() & DS_NO_RESIZE))
+ {
+ SendNotify(UWM_BAR_START);
+ SetCapture();
+ }
+ }
+ break;
+
+ case WM_LBUTTONUP:
+ if (!(m_pDock->GetDockStyle() & DS_NO_RESIZE) && (GetCapture() == this))
+ {
+ SendNotify(UWM_BAR_END);
+ ReleaseCapture();
+ }
+ break;
+
+ case WM_MOUSEMOVE:
+ if (!(m_pDock->GetDockStyle() & DS_NO_RESIZE) && (GetCapture() == this))
+ {
+ SendNotify(UWM_BAR_MOVE);
+ }
+ break;
+ }
+ }
+
+ // pass unhandled messages on for default processing
+ return CWnd::WndProcDefault(uMsg, wParam, lParam);
+ }
+
+
+ ////////////////////////////////////////////////////////////////
+ // Definitions for the CDockClient class nested within CDocker
+ //
+ inline CDocker::CDockClient::CDockClient() : m_pView(0), m_IsClosePressed(FALSE),
+ m_bOldFocus(FALSE), m_bCaptionPressed(FALSE), m_IsTracking(FALSE)
+ {
+ m_Foregnd1 = RGB(32,32,32);
+ m_Backgnd1 = RGB(190,207,227);
+ m_Foregnd2 = GetSysColor(COLOR_BTNTEXT);
+ m_Backgnd2 = GetSysColor(COLOR_BTNFACE);
+ }
+
+ inline void CDocker::CDockClient::Draw3DBorder(RECT& Rect)
+ {
+ // Imitates the drawing of the WS_EX_CLIENTEDGE extended style
+ // This draws a 2 pixel border around the specified Rect
+ CWindowDC dc(this);
+ CRect rcw = Rect;
+ dc.CreatePen(PS_SOLID, 1, GetSysColor(COLOR_3DSHADOW));
+ dc.MoveTo(0, rcw.Height());
+ dc.LineTo(0, 0);
+ dc.LineTo(rcw.Width(), 0);
+ dc.CreatePen(PS_SOLID,1, GetSysColor(COLOR_3DDKSHADOW));
+ dc.MoveTo(1, rcw.Height()-2);
+ dc.LineTo(1, 1);
+ dc.LineTo(rcw.Width()-2, 1);
+ dc.CreatePen(PS_SOLID,1, GetSysColor(COLOR_3DHILIGHT));
+ dc.MoveTo(rcw.Width()-1, 0);
+ dc.LineTo(rcw.Width()-1, rcw.Height()-1);
+ dc.LineTo(0, rcw.Height()-1);
+ dc.CreatePen(PS_SOLID,1, GetSysColor(COLOR_3DLIGHT));
+ dc.MoveTo(rcw.Width()-2, 1);
+ dc.LineTo(rcw.Width()-2, rcw.Height()-2);
+ dc.LineTo(1, rcw.Height()-2);
+ }
+
+ inline CRect CDocker::CDockClient::GetCloseRect()
+ {
+ // Calculate the close rect position in screen co-ordinates
+ CRect rcClose;
+
+ int gap = 4;
+ CRect rc = GetWindowRect();
+ int cx = GetSystemMetrics(SM_CXSMICON);
+ int cy = GetSystemMetrics(SM_CYSMICON);
+
+ rcClose.top = 2 + rc.top + m_pDock->m_NCHeight/2 - cy/2;
+ rcClose.bottom = 2 + rc.top + m_pDock->m_NCHeight/2 + cy/2;
+ rcClose.right = rc.right - gap;
+ rcClose.left = rcClose.right - cx;
+
+#if defined(WINVER) && defined (WS_EX_LAYOUTRTL) && (WINVER >= 0x0500)
+ if (GetWindowLongPtr(GWL_EXSTYLE) & WS_EX_LAYOUTRTL)
+ {
+ rcClose.left = rc.left + gap;
+ rcClose.right = rcClose.left + cx;
+ }
+#endif
+
+
+ return rcClose;
+ }
+
+ inline void CDocker::CDockClient::DrawCaption(WPARAM wParam)
+ {
+ if (IsWindow() && m_pDock->IsDocked() && !(m_pDock->GetDockStyle() & DS_NO_CAPTION))
+ {
+ BOOL bFocus = m_pDock->IsChildOfDocker(GetFocus());
+ m_bOldFocus = FALSE;
+
+ // Acquire the DC for our NonClient painting
+ CDC* pDC;
+ if ((wParam != 1) && (bFocus == m_bOldFocus))
+ pDC = GetDCEx((HRGN)wParam, DCX_WINDOW|DCX_INTERSECTRGN|DCX_PARENTCLIP);
+ else
+ pDC = GetWindowDC();
+
+ // Create and set up our memory DC
+ CRect rc = GetWindowRect();
+ CMemDC dcMem(pDC);
+ int rcAdjust = (GetWindowLongPtr(GWL_EXSTYLE) & WS_EX_CLIENTEDGE)? 2 : 0;
+ int Width = MAX(rc.Width() -rcAdjust, 0);
+ int Height = m_pDock->m_NCHeight + rcAdjust;
+ dcMem.CreateCompatibleBitmap(pDC, Width, Height);
+ m_bOldFocus = bFocus;
+
+ // Set the font for the title
+ NONCLIENTMETRICS info = {0};
+ info.cbSize = GetSizeofNonClientMetrics();
+ SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(info), &info, 0);
+ dcMem.CreateFontIndirect(&info.lfStatusFont);
+
+ // Set the Colours
+ if (bFocus)
+ {
+ dcMem.SetTextColor(m_Foregnd1);
+ dcMem.CreateSolidBrush(m_Backgnd1);
+ dcMem.SetBkColor(m_Backgnd1);
+ }
+ else
+ {
+ dcMem.SetTextColor(m_Foregnd2);
+ dcMem.CreateSolidBrush(m_Backgnd2);
+ dcMem.SetBkColor(m_Backgnd2);
+ }
+
+ // Draw the rectangle
+ dcMem.CreatePen(PS_SOLID, 1, RGB(160, 150, 140));
+ dcMem.Rectangle(rcAdjust, rcAdjust, rc.Width() -rcAdjust, m_pDock->m_NCHeight +rcAdjust);
+
+ // Display the caption
+ int cx = (m_pDock->GetDockStyle() & DS_NO_CLOSE)? 0 : GetSystemMetrics(SM_CXSMICON);
+ CRect rcText(4 +rcAdjust, rcAdjust, rc.Width() -4 - cx -rcAdjust, m_pDock->m_NCHeight +rcAdjust);
+ dcMem.DrawText(m_csCaption, m_csCaption.GetLength(), rcText, DT_LEFT|DT_VCENTER|DT_SINGLELINE|DT_END_ELLIPSIS);
+
+ // Draw the close button
+ if ((0 != m_pDock) && !(m_pDock->GetDockStyle() & DS_NO_CLOSE))
+ DrawCloseButton(dcMem, bFocus);
+
+ // Draw the 3D border
+ if (GetWindowLongPtr(GWL_EXSTYLE) & WS_EX_CLIENTEDGE)
+ Draw3DBorder(rc);
+
+ // Copy the Memory DC to the window's DC
+ pDC->BitBlt(rcAdjust, rcAdjust, Width, Height, &dcMem, rcAdjust, rcAdjust, SRCCOPY);
+
+ // Required for Win98/WinME
+ pDC->Destroy();
+ }
+ }
+
+ inline void CDocker::CDockClient::DrawCloseButton(CDC& DrawDC, BOOL bFocus)
+ {
+ // The close button isn't displayed on Win95
+ if (GetWinVersion() == 1400) return;
+
+ if (m_pDock->IsDocked() && !(m_pDock->GetDockStyle() & DS_NO_CAPTION))
+ {
+ // Determine the close button's drawing position relative to the window
+ CRect rcClose = GetCloseRect();
+ UINT uState = GetCloseRect().PtInRect(GetCursorPos())? m_IsClosePressed && IsLeftButtonDown()? 2 : 1 : 0;
+ ScreenToClient(rcClose);
+
+ if (GetWindowLongPtr(GWL_EXSTYLE) & WS_EX_CLIENTEDGE)
+ {
+ rcClose.OffsetRect(2, m_pDock->m_NCHeight+2);
+ if (GetWindowRect().Height() < (m_pDock->m_NCHeight+4))
+ rcClose.OffsetRect(-2, -2);
+ }
+ else
+ rcClose.OffsetRect(0, m_pDock->m_NCHeight-2);
+
+ // Draw the outer highlight for the close button
+ if (!IsRectEmpty(&rcClose))
+ {
+ switch (uState)
+ {
+ case 0:
+ {
+ // Normal button
+ DrawDC.CreatePen(PS_SOLID, 1, RGB(232, 228, 220));
+ DrawDC.MoveTo(rcClose.left, rcClose.bottom);
+ DrawDC.LineTo(rcClose.right, rcClose.bottom);
+ DrawDC.LineTo(rcClose.right, rcClose.top);
+ DrawDC.LineTo(rcClose.left, rcClose.top);
+ DrawDC.LineTo(rcClose.left, rcClose.bottom);
+ break;
+ }
+
+ case 1:
+ {
+ // Popped up button
+ // Draw outline, white at top, black on bottom
+ DrawDC.CreatePen(PS_SOLID, 1, RGB(0, 0, 0));
+ DrawDC.MoveTo(rcClose.left, rcClose.bottom);
+ DrawDC.LineTo(rcClose.right, rcClose.bottom);
+ DrawDC.LineTo(rcClose.right, rcClose.top);
+ DrawDC.CreatePen(PS_SOLID, 1, RGB(255, 255, 255));
+ DrawDC.LineTo(rcClose.left, rcClose.top);
+ DrawDC.LineTo(rcClose.left, rcClose.bottom);
+ }
+
+ break;
+ case 2:
+ {
+ // Pressed button
+ // Draw outline, black on top, white on bottom
+ DrawDC.CreatePen(PS_SOLID, 1, RGB(255, 255, 255));
+ DrawDC.MoveTo(rcClose.left, rcClose.bottom);
+ DrawDC.LineTo(rcClose.right, rcClose.bottom);
+ DrawDC.LineTo(rcClose.right, rcClose.top);
+ DrawDC.CreatePen(PS_SOLID, 1, RGB(0, 0, 0));
+ DrawDC.LineTo(rcClose.left, rcClose.top);
+ DrawDC.LineTo(rcClose.left, rcClose.bottom);
+ }
+ break;
+ }
+
+ // Manually Draw Close Button
+ if (bFocus)
+ DrawDC.CreatePen(PS_SOLID, 1, m_Foregnd1);
+ else
+ DrawDC.CreatePen(PS_SOLID, 1, m_Foregnd2);
+
+ DrawDC.MoveTo(rcClose.left + 3, rcClose.top +3);
+ DrawDC.LineTo(rcClose.right - 2, rcClose.bottom -2);
+
+ DrawDC.MoveTo(rcClose.left + 4, rcClose.top +3);
+ DrawDC.LineTo(rcClose.right - 2, rcClose.bottom -3);
+
+ DrawDC.MoveTo(rcClose.left + 3, rcClose.top +4);
+ DrawDC.LineTo(rcClose.right - 3, rcClose.bottom -2);
+
+ DrawDC.MoveTo(rcClose.right -3, rcClose.top +3);
+ DrawDC.LineTo(rcClose.left + 2, rcClose.bottom -2);
+
+ DrawDC.MoveTo(rcClose.right -3, rcClose.top +4);
+ DrawDC.LineTo(rcClose.left + 3, rcClose.bottom -2);
+
+ DrawDC.MoveTo(rcClose.right -4, rcClose.top +3);
+ DrawDC.LineTo(rcClose.left + 2, rcClose.bottom -3);
+ }
+ }
+ }
+
+ inline void CDocker::CDockClient::OnNCCalcSize(WPARAM& wParam, LPARAM& lParam)
+ {
+ // Sets the non-client area (and hence sets the client area)
+ // This function modifies lParam
+
+ UNREFERENCED_PARAMETER(wParam);
+
+ if ((0 != m_pDock) && !(m_pDock->GetDockStyle() & DS_NO_CAPTION))
+ {
+ if (m_pDock->IsDocked())
+ {
+ LPRECT rc = (LPRECT)lParam;
+ rc->top += m_pDock->m_NCHeight;
+ }
+ }
+ }
+
+ inline LRESULT CDocker::CDockClient::OnNCHitTest(WPARAM wParam, LPARAM lParam)
+ {
+ // Identify which part of the non-client area the cursor is over
+ if ((0 != m_pDock) && !(m_pDock->GetDockStyle() & DS_NO_CAPTION))
+ {
+ if (m_pDock->IsDocked())
+ {
+ CPoint pt(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
+
+ // Indicate if the point is in the close button (except for Win95)
+ if ((GetWinVersion() > 1400) && (GetCloseRect().PtInRect(pt)))
+ return HTCLOSE;
+
+ ScreenToClient(pt);
+
+ // Indicate if the point is in the caption
+ if (pt.y < 0)
+ return HTCAPTION;
+ }
+ }
+ return CWnd::WndProcDefault(WM_NCHITTEST, wParam, lParam);
+ }
+
+ inline LRESULT CDocker::CDockClient::OnNCLButtonDown(WPARAM wParam, LPARAM lParam)
+ {
+ if ((0 != m_pDock) && !(m_pDock->GetDockStyle() & DS_NO_CAPTION))
+ {
+ if ((HTCLOSE == wParam) && !(m_pDock->GetDockStyle() & DS_NO_CLOSE))
+ {
+ m_IsClosePressed = TRUE;
+ SetCapture();
+ }
+
+ m_bCaptionPressed = TRUE;
+ m_Oldpt.x = GET_X_LPARAM(lParam);
+ m_Oldpt.y = GET_Y_LPARAM(lParam);
+ if (m_pDock->IsDocked())
+ {
+ CPoint pt(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
+ ScreenToClient(pt);
+ m_pView->SetFocus();
+
+ // Update the close button
+ if ((0 != m_pDock) && !(m_pDock->GetDockStyle() & DS_NO_CLOSE))
+ {
+ CWindowDC dc(this);
+ DrawCloseButton(dc, m_bOldFocus);
+ }
+
+ return 0L;
+ }
+ }
+ return CWnd::WndProcDefault(WM_NCLBUTTONDOWN, wParam, lParam);
+ }
+
+ inline void CDocker::CDockClient::OnLButtonUp(WPARAM wParam, LPARAM lParam)
+ {
+ UNREFERENCED_PARAMETER(wParam);
+ UNREFERENCED_PARAMETER(lParam);
+
+ if ((0 != m_pDock) && !(m_pDock->GetDockStyle() & (DS_NO_CAPTION|DS_NO_CLOSE)))
+ {
+ m_bCaptionPressed = FALSE;
+ if (m_IsClosePressed && GetCloseRect().PtInRect(GetCursorPos()))
+ {
+ // Destroy the docker
+ if (dynamic_cast<CDockContainer*>(m_pDock->GetView()))
+ {
+ CDockContainer* pContainer = ((CDockContainer*)m_pDock->GetView())->GetActiveContainer();
+ CDocker* pDock = m_pDock->GetDockFromView(pContainer);
+ pDock->GetDockClient().SetClosePressed();
+ m_pDock->UndockContainer(pContainer, GetCursorPos(), FALSE);
+ pDock->Destroy();
+ }
+ else
+ {
+ m_pDock->Hide();
+ m_pDock->Destroy();
+ }
+ }
+ }
+ }
+
+ inline void CDocker::CDockClient::OnLButtonDown(WPARAM wParam, LPARAM lParam)
+ {
+ UNREFERENCED_PARAMETER(wParam);
+ UNREFERENCED_PARAMETER(lParam);
+
+ m_IsClosePressed = FALSE;
+ ReleaseCapture();
+ CWindowDC dc(this);
+ DrawCloseButton(dc, m_bOldFocus);
+ }
+
+ inline void CDocker::CDockClient::OnMouseActivate(WPARAM wParam, LPARAM lParam)
+ // Focus changed, so redraw the captions
+ {
+ UNREFERENCED_PARAMETER(wParam);
+ UNREFERENCED_PARAMETER(lParam);
+
+ if ((0 != m_pDock) && !(m_pDock->GetDockStyle() & DS_NO_CAPTION))
+ {
+ m_pDock->GetDockAncestor()->PostMessage(UWM_DOCK_ACTIVATED, 0, 0);
+ }
+ }
+
+ inline void CDocker::CDockClient::OnMouseMove(WPARAM wParam, LPARAM lParam)
+ {
+ OnNCMouseMove(wParam, lParam);
+ }
+
+ inline void CDocker::CDockClient::OnNCMouseLeave(WPARAM wParam, LPARAM lParam)
+ {
+ UNREFERENCED_PARAMETER(wParam);
+ UNREFERENCED_PARAMETER(lParam);
+
+ m_IsTracking = FALSE;
+ CWindowDC dc(this);
+ if ((0 != m_pDock) && !(m_pDock->GetDockStyle() & (DS_NO_CAPTION|DS_NO_CLOSE)) && m_pDock->IsDocked())
+ DrawCloseButton(dc, m_bOldFocus);
+
+ m_IsTracking = FALSE;
+ }
+
+ inline LRESULT CDocker::CDockClient::OnNCMouseMove(WPARAM wParam, LPARAM lParam)
+ {
+ if (!m_IsTracking)
+ {
+ TRACKMOUSEEVENT TrackMouseEventStruct = {0};
+ TrackMouseEventStruct.cbSize = sizeof(TrackMouseEventStruct);
+ TrackMouseEventStruct.dwFlags = TME_LEAVE|TME_NONCLIENT;
+ TrackMouseEventStruct.hwndTrack = m_hWnd;
+ _TrackMouseEvent(&TrackMouseEventStruct);
+ m_IsTracking = TRUE;
+ }
+
+ if ((0 != m_pDock) && !(m_pDock->GetDockStyle() & DS_NO_CAPTION))
+ {
+ if (m_pDock->IsDocked())
+ {
+ // Discard phantom mouse move messages
+ if ( (m_Oldpt.x == GET_X_LPARAM(lParam) ) && (m_Oldpt.y == GET_Y_LPARAM(lParam)))
+ return 0L;
+
+ if (IsLeftButtonDown() && (wParam == HTCAPTION) && (m_bCaptionPressed))
+ {
+ CDocker* pDock = (CDocker*)GetParent();
+ if (pDock)
+ pDock->Undock(GetCursorPos());
+ }
+
+ // Update the close button
+ if ((0 != m_pDock) && !(m_pDock->GetDockStyle() & DS_NO_CLOSE))
+ {
+ CWindowDC dc(this);
+ DrawCloseButton(dc, m_bOldFocus);
+ }
+ }
+
+ m_bCaptionPressed = FALSE;
+ }
+ return CWnd::WndProcDefault(WM_MOUSEMOVE, wParam, lParam);
+ }
+
+ inline LRESULT CDocker::CDockClient::OnNCPaint(WPARAM wParam, LPARAM lParam)
+ {
+ if ((0 != m_pDock) && !(m_pDock->GetDockStyle() & DS_NO_CAPTION))
+ {
+ if (m_pDock->IsDocked())
+ {
+ DefWindowProc(WM_NCPAINT, wParam, lParam);
+ DrawCaption(wParam);
+ return 0;
+ }
+ }
+ return CWnd::WndProcDefault(WM_NCPAINT, wParam, lParam);
+ }
+
+ inline void CDocker::CDockClient::OnWindowPosChanged(WPARAM wParam, LPARAM lParam)
+ {
+ UNREFERENCED_PARAMETER(wParam);
+ UNREFERENCED_PARAMETER(lParam);
+
+ // Reposition the View window to cover the DockClient's client area
+ CRect rc = GetClientRect();
+ m_pView->SetWindowPos(NULL, rc, SWP_SHOWWINDOW);
+ }
+
+ inline void CDocker::CDockClient::PreRegisterClass(WNDCLASS& wc)
+ {
+ wc.lpszClassName = _T("Win32++ DockClient");
+ wc.hCursor = ::LoadCursor(NULL, IDC_ARROW);
+ }
+
+ inline void CDocker::CDockClient::PreCreate(CREATESTRUCT& cs)
+ {
+ DWORD dwStyle = m_pDock->GetDockStyle();
+ if (dwStyle & DS_CLIENTEDGE)
+ cs.dwExStyle = WS_EX_CLIENTEDGE;
+
+#if defined(WINVER) && defined (WS_EX_LAYOUTRTL) && (WINVER >= 0x0500)
+ if (m_pDock->GetWindowLongPtr(GWL_EXSTYLE) & WS_EX_LAYOUTRTL)
+ cs.dwExStyle |= WS_EX_LAYOUTRTL;
+#endif
+
+ }
+
+ inline void CDocker::CDockClient::SendNotify(UINT nMessageID)
+ {
+ // Fill the DragPos structure with data
+ DRAGPOS DragPos;
+ DragPos.hdr.code = nMessageID;
+ DragPos.hdr.hwndFrom = m_hWnd;
+ DragPos.ptPos = GetCursorPos();
+
+ // Send a DragPos notification to the docker
+ GetParent()->SendMessage(WM_NOTIFY, 0L, (LPARAM)&DragPos);
+ }
+
+ inline void CDocker::CDockClient::SetCaptionColors(COLORREF Foregnd1, COLORREF Backgnd1, COLORREF Foregnd2, COLORREF Backgnd2)
+ {
+ // Set the colors used when drawing the caption
+ // m_Foregnd1 Foreground colour (focused). m_Backgnd1 Background colour (focused)
+ // m_Foregnd2 Foreground colour (not focused). m_Backgnd2 Foreground colour (not focused)
+ m_Foregnd1 = Foregnd1;
+ m_Backgnd1 = Backgnd1;
+ m_Foregnd2 = Foregnd2;
+ m_Backgnd2 = Backgnd2;
+ }
+
+ inline LRESULT CDocker::CDockClient::WndProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam)
+ {
+ switch (uMsg)
+ {
+ case WM_LBUTTONUP:
+ {
+ ReleaseCapture();
+ if ((0 != m_pDock) && !(m_pDock->GetDockStyle() & DS_NO_CLOSE))
+ {
+ CWindowDC dc(this);
+ DrawCloseButton(dc, m_bOldFocus);
+ OnLButtonUp(wParam, lParam);
+ }
+ }
+ break;
+
+ case WM_MOUSEACTIVATE:
+ OnMouseActivate(wParam, lParam);
+ break;
+
+ case WM_MOUSEMOVE:
+ OnMouseMove(wParam, lParam);
+ break;
+
+ case WM_NCCALCSIZE:
+ OnNCCalcSize(wParam, lParam);
+ break;
+
+ case WM_NCHITTEST:
+ return OnNCHitTest(wParam, lParam);
+
+ case WM_NCLBUTTONDOWN:
+ return OnNCLButtonDown(wParam, lParam);
+
+ case WM_NCMOUSEMOVE:
+ return OnNCMouseMove(wParam, lParam);
+
+ case WM_NCPAINT:
+ return OnNCPaint(wParam, lParam);
+
+ case WM_NCMOUSELEAVE:
+ OnNCMouseLeave(wParam, lParam);
+ break;
+
+ case WM_WINDOWPOSCHANGED:
+ OnWindowPosChanged(wParam, lParam);
+ break;
+ }
+
+ return CWnd::WndProcDefault(uMsg, wParam, lParam);
+ }
+
+
+ //////////////////////////////////////////////////////////////
+ // Definitions for the CDockHint class nested within CDocker
+ //
+ inline CDocker::CDockHint::CDockHint() : m_uDockSideOld(0)
+ {
+ }
+
+ inline CDocker::CDockHint::~CDockHint()
+ {
+ }
+
+ inline RECT CDocker::CDockHint::CalcHintRectContainer(CDocker* pDockTarget)
+ {
+ // Calculate the hint window's position for container docking
+ CRect rcHint = pDockTarget->GetDockClient().GetWindowRect();
+ if (pDockTarget->GetDockClient().GetWindowLongPtr(GWL_EXSTYLE) & WS_EX_CLIENTEDGE)
+ rcHint.InflateRect(-2, -2);
+ pDockTarget->ScreenToClient(rcHint);
+
+ return rcHint;
+ }
+
+ inline RECT CDocker::CDockHint::CalcHintRectInner(CDocker* pDockTarget, CDocker* pDockDrag, UINT uDockSide)
+ {
+ // Calculate the hint window's position for inner docking
+ CRect rcHint = pDockTarget->GetDockClient().GetWindowRect();
+ if (pDockTarget->GetDockClient().GetWindowLongPtr(GWL_EXSTYLE) & WS_EX_CLIENTEDGE)
+ rcHint.InflateRect(-2, -2);
+ pDockTarget->ScreenToClient(rcHint);
+
+ int Width;
+ CRect rcDockDrag = pDockDrag->GetWindowRect();
+ CRect rcDockTarget = pDockTarget->GetDockClient().GetWindowRect();
+ if ((uDockSide == DS_DOCKED_LEFT) || (uDockSide == DS_DOCKED_RIGHT))
+ {
+ Width = rcDockDrag.Width();
+ if (Width >= (rcDockTarget.Width() - pDockDrag->GetBarWidth()))
+ Width = MAX(rcDockTarget.Width()/2 - pDockDrag->GetBarWidth(), pDockDrag->GetBarWidth());
+ }
+ else
+ {
+ Width = rcDockDrag.Height();
+ if (Width >= (rcDockTarget.Height() - pDockDrag->GetBarWidth()))
+ Width = MAX(rcDockTarget.Height()/2 - pDockDrag->GetBarWidth(), pDockDrag->GetBarWidth());
+ }
+ switch (uDockSide)
+ {
+ case DS_DOCKED_LEFT:
+ rcHint.right = rcHint.left + Width;
+ break;
+ case DS_DOCKED_RIGHT:
+ rcHint.left = rcHint.right - Width;
+ break;
+ case DS_DOCKED_TOP:
+ rcHint.bottom = rcHint.top + Width;
+ break;
+ case DS_DOCKED_BOTTOM:
+ rcHint.top = rcHint.bottom - Width;
+ break;
+ }
+
+ return rcHint;
+ }
+
+ inline RECT CDocker::CDockHint::CalcHintRectOuter(CDocker* pDockDrag, UINT uDockSide)
+ {
+ // Calculate the hint window's position for outer docking
+ CDocker* pDockTarget = pDockDrag->GetDockAncestor();
+ CRect rcHint = pDockTarget->GetClientRect();
+ if (pDockTarget->GetDockClient().GetWindowLongPtr(GWL_EXSTYLE) & WS_EX_CLIENTEDGE)
+ rcHint.InflateRect(-2, -2);
+
+ int Width;
+ CRect rcDockDrag = pDockDrag->GetWindowRect();
+ CRect rcDockTarget = pDockTarget->GetDockClient().GetWindowRect();
+
+ // Limit the docked size to half the parent's size if it won't fit inside parent
+ if ((uDockSide == DS_DOCKED_LEFTMOST) || (uDockSide == DS_DOCKED_RIGHTMOST))
+ {
+ Width = rcDockDrag.Width();
+ int BarWidth = pDockDrag->GetBarWidth();
+ if (Width >= pDockTarget->GetDockClient().GetClientRect().Width() - pDockDrag->GetBarWidth())
+ Width = MAX(pDockTarget->GetDockClient().GetClientRect().Width()/2 - BarWidth, BarWidth);
+ }
+ else
+ {
+ Width = rcDockDrag.Height();
+ int BarWidth = pDockDrag->GetBarWidth();
+ if (Width >= pDockTarget->GetDockClient().GetClientRect().Height() - pDockDrag->GetBarWidth())
+ Width = MAX(pDockTarget->GetDockClient().GetClientRect().Height()/2 - BarWidth, BarWidth);
+ }
+ switch (uDockSide)
+ {
+ case DS_DOCKED_LEFTMOST:
+ rcHint.right = rcHint.left + Width;
+ break;
+ case DS_DOCKED_RIGHTMOST:
+ rcHint.left = rcHint.right - Width;
+ break;
+ case DS_DOCKED_TOPMOST:
+ rcHint.bottom = rcHint.top + Width;
+ break;
+ case DS_DOCKED_BOTTOMMOST:
+ rcHint.top = rcHint.bottom - Width;
+ break;
+ }
+
+ return rcHint;
+ }
+
+ inline void CDocker::CDockHint::DisplayHint(CDocker* pDockTarget, CDocker* pDockDrag, UINT uDockSide)
+ {
+ // Ensure a new hint window is created if dock side changes
+ if (uDockSide != m_uDockSideOld)
+ {
+ Destroy();
+ pDockTarget->RedrawWindow( NULL, NULL, RDW_NOERASE | RDW_UPDATENOW );
+ pDockDrag->RedrawWindow();
+ }
+ m_uDockSideOld = uDockSide;
+
+ if (!IsWindow())
+ {
+ CRect rcHint;
+
+ if (uDockSide & 0xF)
+ rcHint = CalcHintRectInner(pDockTarget, pDockDrag, uDockSide);
+ else if (uDockSide & 0xF0000)
+ rcHint = CalcHintRectOuter(pDockDrag, uDockSide);
+ else if (uDockSide & DS_DOCKED_CONTAINER)
+ rcHint = CalcHintRectContainer(pDockTarget);
+ else
+ return;
+
+ ShowHintWindow(pDockTarget, rcHint);
+ }
+ }
+
+ inline void CDocker::CDockHint::OnDraw(CDC* pDC)
+ {
+ // Display the blue tinted bitmap
+ CRect rc = GetClientRect();
+ CMemDC MemDC(pDC);
+ MemDC.SelectObject(&m_bmBlueTint);
+ pDC->BitBlt(0, 0, rc.Width(), rc.Height(), &MemDC, 0, 0, SRCCOPY);
+ }
+
+ inline void CDocker::CDockHint::PreCreate(CREATESTRUCT &cs)
+ {
+ cs.style = WS_POPUP;
+
+ // WS_EX_TOOLWINDOW prevents the window being displayed on the taskbar
+ cs.dwExStyle = WS_EX_TOOLWINDOW;
+
+ cs.lpszClass = _T("Win32++ DockHint");
+ }
+
+ inline void CDocker::CDockHint::ShowHintWindow(CDocker* pDockTarget, CRect rcHint)
+ {
+ // Save the Dock window's blue tinted bitmap
+ CClientDC dcDesktop(NULL);
+ CMemDC dcMem(&dcDesktop);
+ CRect rcBitmap = rcHint;
+ CRect rcTarget = rcHint;
+ pDockTarget->ClientToScreen(rcTarget);
+
+ m_bmBlueTint.CreateCompatibleBitmap(&dcDesktop, rcBitmap.Width(), rcBitmap.Height());
+ CBitmap* pOldBitmap = dcMem.SelectObject(&m_bmBlueTint);
+ dcMem.BitBlt(0, 0, rcBitmap.Width(), rcBitmap.Height(), &dcDesktop, rcTarget.left, rcTarget.top, SRCCOPY);
+ dcMem.SelectObject(pOldBitmap);
+ TintBitmap(&m_bmBlueTint, -64, -24, +128);
+
+ // Create the Hint window
+ if (!IsWindow())
+ {
+ Create(pDockTarget);
+ }
+
+ pDockTarget->ClientToScreen(rcHint);
+ SetWindowPos(NULL, rcHint, SWP_SHOWWINDOW|SWP_NOZORDER|SWP_NOACTIVATE);
+ }
+
+
+ ////////////////////////////////////////////////////////////////
+ // Definitions for the CTargetCentre class nested within CDocker
+ //
+ inline CDocker::CTargetCentre::CTargetCentre() : m_bIsOverContainer(FALSE), m_pOldDockTarget(0)
+ {
+ }
+
+ inline CDocker::CTargetCentre::~CTargetCentre()
+ {
+ }
+
+ inline void CDocker::CTargetCentre::OnDraw(CDC* pDC)
+ {
+ CBitmap bmCentre(IDW_SDCENTER);
+ CBitmap bmLeft(IDW_SDLEFT);
+ CBitmap bmRight(IDW_SDRIGHT);
+ CBitmap bmTop(IDW_SDTOP);
+ CBitmap bmBottom(IDW_SDBOTTOM);
+
+ if (bmCentre.GetHandle()) pDC->DrawBitmap(0, 0, 88, 88, bmCentre, RGB(255,0,255));
+ else TRACE(_T("Missing docking resource: Target Centre\n"));
+
+ if (bmLeft.GetHandle()) pDC->DrawBitmap(0, 29, 31, 29, bmLeft, RGB(255,0,255));
+ else TRACE(_T("Missing docking resource: Target Left\n"));
+
+ if (bmTop.GetHandle()) pDC->DrawBitmap(29, 0, 29, 31, bmTop, RGB(255,0,255));
+ else TRACE(_T("Missing docking resource: Target Top\n"));
+
+ if (bmRight.GetHandle()) pDC->DrawBitmap(55, 29, 31, 29, bmRight, RGB(255,0,255));
+ else TRACE(_T("Missing docking resource: Target Right\n"));
+
+ if (bmBottom.GetHandle()) pDC->DrawBitmap(29, 55, 29, 31, bmBottom, RGB(255,0,255));
+ else TRACE(_T("Missing docking resource: Target Bottom\n"));
+
+ if (IsOverContainer())
+ {
+ CBitmap bmMiddle(IDW_SDMIDDLE);
+ pDC->DrawBitmap(31, 31, 25, 26, bmMiddle, RGB(255,0,255));
+ }
+ }
+
+ inline void CDocker::CTargetCentre::OnCreate()
+ {
+ // Use a region to create an irregularly shapped window
+ POINT ptArray[16] = { {0,29}, {22, 29}, {29, 22}, {29, 0},
+ {58, 0}, {58, 22}, {64, 29}, {87, 29},
+ {87, 58}, {64, 58}, {58, 64}, {58, 87},
+ {29, 87}, {29, 64}, {23, 58}, {0, 58} };
+
+ CRgn rgnPoly;
+ rgnPoly.CreatePolygonRgn(ptArray, 16, WINDING);
+ SetWindowRgn(&rgnPoly, FALSE);
+ }
+
+ inline BOOL CDocker::CTargetCentre::CheckTarget(LPDRAGPOS pDragPos)
+ {
+ CDocker* pDockDrag = (CDocker*)FromHandle(pDragPos->hdr.hwndFrom);
+ if (NULL == pDockDrag) return FALSE;
+
+ CDocker* pDockTarget = pDockDrag->GetDockFromPoint(pDragPos->ptPos);
+ if (NULL == pDockTarget) return FALSE;
+
+ if (!IsWindow()) Create();
+ m_bIsOverContainer = (dynamic_cast<CDockContainer*>(pDockTarget->GetView()) != NULL);
+
+ // Redraw the target if the dock target changes
+ if (m_pOldDockTarget != pDockTarget) Invalidate();
+ m_pOldDockTarget = pDockTarget;
+
+ int cxImage = 88;
+ int cyImage = 88;
+
+ CRect rcTarget = pDockTarget->GetDockClient().GetWindowRect();
+ int xMid = rcTarget.left + (rcTarget.Width() - cxImage)/2;
+ int yMid = rcTarget.top + (rcTarget.Height() - cyImage)/2;
+ SetWindowPos(HWND_TOPMOST, xMid, yMid, cxImage, cyImage, SWP_NOACTIVATE|SWP_SHOWWINDOW);
+
+ // Create the docking zone rectangles
+ CPoint pt = pDragPos->ptPos;
+ ScreenToClient(pt);
+ CRect rcLeft(0, 29, 31, 58);
+ CRect rcTop(29, 0, 58, 31);
+ CRect rcRight(55, 29, 87, 58);
+ CRect rcBottom(29, 55, 58, 87);
+ CRect rcMiddle(31, 31, 56, 57);
+
+ // Test if our cursor is in one of the docking zones
+ if ((rcLeft.PtInRect(pt)) && !(pDockTarget->GetDockStyle() & DS_NO_DOCKCHILD_LEFT))
+ {
+ pDockDrag->m_BlockMove = TRUE;
+ pDockTarget->GetDockHint().DisplayHint(pDockTarget, pDockDrag, DS_DOCKED_LEFT);
+ pDockDrag->m_dwDockZone = DS_DOCKED_LEFT;
+ return TRUE;
+ }
+ else if ((rcTop.PtInRect(pt)) && !(pDockTarget->GetDockStyle() & DS_NO_DOCKCHILD_TOP))
+ {
+ pDockDrag->m_BlockMove = TRUE;
+ pDockTarget->GetDockHint().DisplayHint(pDockTarget, pDockDrag, DS_DOCKED_TOP);
+ pDockDrag->m_dwDockZone = DS_DOCKED_TOP;
+ return TRUE;
+ }
+ else if ((rcRight.PtInRect(pt)) && !(pDockTarget->GetDockStyle() & DS_NO_DOCKCHILD_RIGHT))
+ {
+ pDockDrag->m_BlockMove = TRUE;
+ pDockTarget->GetDockHint().DisplayHint(pDockTarget, pDockDrag, DS_DOCKED_RIGHT);
+ pDockDrag->m_dwDockZone = DS_DOCKED_RIGHT;
+ return TRUE;
+ }
+ else if ((rcBottom.PtInRect(pt)) && !(pDockTarget->GetDockStyle() & DS_NO_DOCKCHILD_BOTTOM))
+ {
+ pDockDrag->m_BlockMove = TRUE;
+ pDockTarget->GetDockHint().DisplayHint(pDockTarget, pDockDrag, DS_DOCKED_BOTTOM);
+ pDockDrag->m_dwDockZone = DS_DOCKED_BOTTOM;
+ return TRUE;
+ }
+ else if ((rcMiddle.PtInRect(pt)) && (IsOverContainer()))
+ {
+ pDockDrag->m_BlockMove = TRUE;
+ pDockTarget->GetDockHint().DisplayHint(pDockTarget, pDockDrag, DS_DOCKED_CONTAINER);
+ pDockDrag->m_dwDockZone = DS_DOCKED_CONTAINER;
+ return TRUE;
+ }
+ else
+ return FALSE;
+ }
+
+ ////////////////////////////////////////////////////////////////
+ // Definitions for the CTarget class nested within CDocker
+ // CTarget is the base class for a number of CTargetXXX classes
+ inline CDocker::CTarget::~CTarget()
+ {
+ }
+
+ inline void CDocker::CTarget::OnDraw(CDC* pDC)
+ {
+ BITMAP bm = m_bmImage.GetBitmapData();
+ int cxImage = bm.bmWidth;
+ int cyImage = bm.bmHeight;
+
+ if (m_bmImage)
+ pDC->DrawBitmap(0, 0, cxImage, cyImage, m_bmImage, RGB(255,0,255));
+ else
+ TRACE(_T("Missing docking resource\n"));
+ }
+
+ inline void CDocker::CTarget::PreCreate(CREATESTRUCT &cs)
+ {
+ cs.style = WS_POPUP;
+ cs.dwExStyle = WS_EX_TOPMOST|WS_EX_TOOLWINDOW;
+ cs.lpszClass = _T("Win32++ DockTargeting");
+ }
+
+
+ ////////////////////////////////////////////////////////////////
+ // Definitions for the CTargetLeft class nested within CDocker
+ //
+ inline BOOL CDocker::CTargetLeft::CheckTarget(LPDRAGPOS pDragPos)
+ {
+ CDocker* pDockDrag = (CDocker*)FromHandle(pDragPos->hdr.hwndFrom);
+ if (NULL == pDockDrag) return FALSE;
+
+ CPoint pt = pDragPos->ptPos;
+ CDocker* pDockTarget = pDockDrag->GetDockFromPoint(pt)->GetTopmostDocker();
+ if (pDockTarget != pDockDrag->GetDockAncestor())
+ {
+ Destroy();
+ return FALSE;
+ }
+
+ BITMAP bm = m_bmImage.GetBitmapData();
+ int cxImage = bm.bmWidth;
+ int cyImage = bm.bmHeight;
+
+ if (!IsWindow())
+ {
+ Create();
+ CRect rc = pDockTarget->GetWindowRect();
+ int yMid = rc.top + (rc.Height() - cyImage)/2;
+ SetWindowPos(HWND_TOPMOST, rc.left + 10, yMid, cxImage, cyImage, SWP_NOACTIVATE|SWP_SHOWWINDOW);
+ }
+
+ CRect rcLeft(0, 0, cxImage, cyImage);
+ ScreenToClient(pt);
+
+ // Test if our cursor is in one of the docking zones
+ if ((rcLeft.PtInRect(pt)) && !(pDockTarget->GetDockStyle() & DS_NO_DOCKCHILD_LEFT))
+ {
+ pDockDrag->m_BlockMove = TRUE;
+ pDockTarget->GetDockHint().DisplayHint(pDockTarget, pDockDrag, DS_DOCKED_LEFTMOST);
+ pDockDrag->m_dwDockZone = DS_DOCKED_LEFTMOST;
+ return TRUE;
+ }
+
+ return FALSE;
+ }
+
+
+ ////////////////////////////////////////////////////////////////
+ // Definitions for the CTargetTop class nested within CDocker
+ //
+ inline BOOL CDocker::CTargetTop::CheckTarget(LPDRAGPOS pDragPos)
+ {
+ CDocker* pDockDrag = (CDocker*)FromHandle(pDragPos->hdr.hwndFrom);
+ if (NULL == pDockDrag) return FALSE;
+
+ CPoint pt = pDragPos->ptPos;
+ CDocker* pDockTarget = pDockDrag->GetDockFromPoint(pt)->GetTopmostDocker();
+ if (pDockTarget != pDockDrag->GetDockAncestor())
+ {
+ Destroy();
+ return FALSE;
+ }
+
+ BITMAP bm = m_bmImage.GetBitmapData();
+ int cxImage = bm.bmWidth;
+ int cyImage = bm.bmHeight;
+
+ if (!IsWindow())
+ {
+ Create();
+ CRect rc = pDockTarget->GetWindowRect();
+ int xMid = rc.left + (rc.Width() - cxImage)/2;
+ SetWindowPos(HWND_TOPMOST, xMid, rc.top + 10, cxImage, cyImage, SWP_NOACTIVATE|SWP_SHOWWINDOW);
+ }
+
+ CRect rcTop(0, 0, cxImage, cyImage);
+ ScreenToClient(pt);
+
+ // Test if our cursor is in one of the docking zones
+ if ((rcTop.PtInRect(pt)) && !(pDockTarget->GetDockStyle() & DS_NO_DOCKCHILD_TOP))
+ {
+ pDockDrag->m_BlockMove = TRUE;
+ pDockTarget->GetDockHint().DisplayHint(pDockTarget, pDockDrag, DS_DOCKED_TOPMOST);
+ pDockDrag->m_dwDockZone = DS_DOCKED_TOPMOST;
+ return TRUE;
+ }
+
+ return FALSE;
+ }
+
+
+ ////////////////////////////////////////////////////////////////
+ // Definitions for the CTargetRight class nested within CDocker
+ //
+ inline BOOL CDocker::CTargetRight::CheckTarget(LPDRAGPOS pDragPos)
+ {
+ CDocker* pDockDrag = (CDocker*)FromHandle(pDragPos->hdr.hwndFrom);
+ if (NULL == pDockDrag) return FALSE;
+
+ CPoint pt = pDragPos->ptPos;
+ CDocker* pDockTarget = pDockDrag->GetDockFromPoint(pt)->GetTopmostDocker();
+ if (pDockTarget != pDockDrag->GetDockAncestor())
+ {
+ Destroy();
+ return FALSE;
+ }
+
+ BITMAP bm = m_bmImage.GetBitmapData();
+ int cxImage = bm.bmWidth;
+ int cyImage = bm.bmHeight;
+
+ if (!IsWindow())
+ {
+ Create();
+ CRect rc = pDockTarget->GetWindowRect();
+ int yMid = rc.top + (rc.Height() - cyImage)/2;
+ SetWindowPos(HWND_TOPMOST, rc.right - 10 - cxImage, yMid, cxImage, cyImage, SWP_NOACTIVATE|SWP_SHOWWINDOW);
+ }
+
+ CRect rcRight(0, 0, cxImage, cyImage);
+ ScreenToClient(pt);
+
+ // Test if our cursor is in one of the docking zones
+ if ((rcRight.PtInRect(pt)) && !(pDockTarget->GetDockStyle() & DS_NO_DOCKCHILD_RIGHT))
+ {
+ pDockDrag->m_BlockMove = TRUE;
+ pDockTarget->GetDockHint().DisplayHint(pDockTarget, pDockDrag, DS_DOCKED_RIGHTMOST);
+ pDockDrag->m_dwDockZone = DS_DOCKED_RIGHTMOST;
+ return TRUE;
+ }
+
+ return FALSE;
+ }
+
+
+ ////////////////////////////////////////////////////////////////
+ // Definitions for the CTargetBottom class nested within CDocker
+ //
+ inline BOOL CDocker::CTargetBottom::CheckTarget(LPDRAGPOS pDragPos)
+ {
+ CDocker* pDockDrag = (CDocker*)FromHandle(pDragPos->hdr.hwndFrom);
+ if (NULL == pDockDrag) return FALSE;
+
+ CPoint pt = pDragPos->ptPos;
+ CDocker* pDockTarget = pDockDrag->GetDockFromPoint(pt)->GetTopmostDocker();
+ if (pDockTarget != pDockDrag->GetDockAncestor())
+ {
+ Destroy();
+ return FALSE;
+ }
+
+ BITMAP bm = m_bmImage.GetBitmapData();
+ int cxImage = bm.bmWidth;
+ int cyImage = bm.bmHeight;
+
+ if (!IsWindow())
+ {
+ Create();
+ CRect rc = pDockTarget->GetWindowRect();
+ int xMid = rc.left + (rc.Width() - cxImage)/2;
+ SetWindowPos(HWND_TOPMOST, xMid, rc.bottom - 10 - cyImage, cxImage, cyImage, SWP_NOACTIVATE|SWP_SHOWWINDOW);
+ }
+ CRect rcBottom(0, 0, cxImage, cyImage);
+ ScreenToClient(pt);
+
+ // Test if our cursor is in one of the docking zones
+ if ((rcBottom.PtInRect(pt)) && !(pDockTarget->GetDockStyle() & DS_NO_DOCKCHILD_BOTTOM))
+ {
+ pDockDrag->m_BlockMove = TRUE;
+ pDockTarget->GetDockHint().DisplayHint(pDockTarget, pDockDrag, DS_DOCKED_BOTTOMMOST);
+ pDockDrag->m_dwDockZone = DS_DOCKED_BOTTOMMOST;
+ return TRUE;
+ }
+
+ return FALSE;
+ }
+
+
+ /////////////////////////////////////////
+ // Definitions for the CDocker class
+ //
+ inline CDocker::CDocker() : m_pDockParent(NULL), m_pDockActive(NULL), m_BlockMove(FALSE), m_Undocking(FALSE),
+ m_bIsClosing(FALSE), m_bIsDragging(FALSE), m_bDragAutoResize(TRUE), m_DockStartSize(0), m_nDockID(0),
+ m_nTimerCount(0), m_NCHeight(0), m_dwDockZone(0), m_DockSizeRatio(1.0), m_DockStyle(0), m_hOldFocus(0)
+ {
+ // Assume this docker is the DockAncestor for now.
+ m_pDockAncestor = this;
+ }
+
+ inline CDocker::~CDocker()
+ {
+ GetDockBar().Destroy();
+
+ std::vector <DockPtr>::iterator iter;
+ if (GetDockAncestor() == this)
+ {
+ // Destroy all dock descendants of this dock ancestor
+ for (iter = GetAllDockers().begin(); iter < GetAllDockers().end(); ++iter)
+ {
+ (*iter)->Destroy();
+ }
+ }
+ }
+
+ inline CDocker* CDocker::AddDockedChild(CDocker* pDocker, DWORD dwDockStyle, int DockSize, int nDockID /* = 0*/)
+ // This function creates the docker, and adds it to the docker heirachy as docked
+ {
+ // Create the docker window as a child of the frame window.
+ // This pernamently sets the frame window as the docker window's owner,
+ // even when its parent is subsequently changed.
+
+ assert(pDocker);
+
+ // Store the Docker's pointer in the DockAncestor's vector for later deletion
+ GetDockAncestor()->m_vAllDockers.push_back(DockPtr(pDocker));
+
+ pDocker->SetDockStyle(dwDockStyle);
+ pDocker->m_nDockID = nDockID;
+ pDocker->m_pDockAncestor = GetDockAncestor();
+ pDocker->m_pDockParent = this;
+ pDocker->SetDockSize(DockSize);
+ CWnd* pFrame = GetDockAncestor()->GetAncestor();
+ pDocker->Create(pFrame);
+ pDocker->SetParent(this);
+
+ // Dock the docker window
+ if (dwDockStyle & DS_DOCKED_CONTAINER)
+ DockInContainer(pDocker, dwDockStyle);
+ else
+ Dock(pDocker, dwDockStyle);
+
+ // Issue TRACE warnings for any missing resources
+ HMODULE hMod= GetApp()->GetResourceHandle();
+
+ if (!(dwDockStyle & DS_NO_RESIZE))
+ {
+ if (!FindResource(hMod, MAKEINTRESOURCE(IDW_SPLITH), RT_GROUP_CURSOR))
+ TRACE(_T("**WARNING** Horizontal cursor resource missing\n"));
+ if (!FindResource(hMod, MAKEINTRESOURCE(IDW_SPLITV), RT_GROUP_CURSOR))
+ TRACE(_T("**WARNING** Vertical cursor resource missing\n"));
+ }
+
+ if (!(dwDockStyle & DS_NO_UNDOCK))
+ {
+ if (!FindResource(hMod, MAKEINTRESOURCE(IDW_SDCENTER), RT_BITMAP))
+ TRACE(_T("**WARNING** Docking center bitmap resource missing\n"));
+ if (!FindResource(hMod, MAKEINTRESOURCE(IDW_SDLEFT), RT_BITMAP))
+ TRACE(_T("**WARNING** Docking left bitmap resource missing\n"));
+ if (!FindResource(hMod, MAKEINTRESOURCE(IDW_SDRIGHT), RT_BITMAP))
+ TRACE(_T("**WARNING** Docking right bitmap resource missing\n"));
+ if (!FindResource(hMod, MAKEINTRESOURCE(IDW_SDTOP), RT_BITMAP))
+ TRACE(_T("**WARNING** Docking top bitmap resource missing\n"));
+ if (!FindResource(hMod, MAKEINTRESOURCE(IDW_SDBOTTOM), RT_BITMAP))
+ TRACE(_T("**WARNING** Docking center bottom resource missing\n"));
+ }
+
+ if (dwDockStyle & DS_DOCKED_CONTAINER)
+ {
+ if (!FindResource(hMod, MAKEINTRESOURCE(IDW_SDMIDDLE), RT_BITMAP))
+ TRACE(_T("**WARNING** Docking container bitmap resource missing\n"));
+ }
+
+ return pDocker;
+ }
+
+ inline CDocker* CDocker::AddUndockedChild(CDocker* pDocker, DWORD dwDockStyle, int DockSize, RECT rc, int nDockID /* = 0*/)
+ // This function creates the docker, and adds it to the docker heirachy as undocked
+ {
+ assert(pDocker);
+
+ // Store the Docker's pointer in the DockAncestor's vector for later deletion
+ GetDockAncestor()->m_vAllDockers.push_back(DockPtr(pDocker));
+
+ pDocker->SetDockSize(DockSize);
+ pDocker->SetDockStyle(dwDockStyle & 0XFFFFFF0);
+ pDocker->m_nDockID = nDockID;
+ pDocker->m_pDockAncestor = GetDockAncestor();
+
+ // Initially create the as a child window of the frame
+ // This makes the frame window the owner of our docker
+ CWnd* pFrame = GetDockAncestor()->GetAncestor();
+ pDocker->Create(pFrame);
+ pDocker->SetParent(this);
+
+ // Change the Docker to a POPUP window
+ DWORD dwStyle = WS_POPUP| WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_VISIBLE;
+ pDocker->SetWindowLongPtr(GWL_STYLE, dwStyle);
+ pDocker->SetRedraw(FALSE);
+ pDocker->SetParent(0);
+ pDocker->SetWindowPos(HWND_TOP, rc, SWP_SHOWWINDOW|SWP_FRAMECHANGED);
+ pDocker->SetRedraw(TRUE);
+ pDocker->RedrawWindow(0, 0, RDW_INVALIDATE|RDW_UPDATENOW|RDW_ERASE|RDW_ALLCHILDREN);
+ pDocker->SetWindowText(pDocker->GetCaption().c_str());
+
+ return pDocker;
+ }
+
+ inline void CDocker::CheckAllTargets(LPDRAGPOS pDragPos)
+ // Calls CheckTarget for each possible target zone
+ {
+ if (!GetDockAncestor()->m_TargetCentre.CheckTarget(pDragPos))
+ {
+ if (!GetDockAncestor()->m_TargetLeft.CheckTarget(pDragPos))
+ {
+ if(!GetDockAncestor()->m_TargetTop.CheckTarget(pDragPos))
+ {
+ if(!GetDockAncestor()->m_TargetRight.CheckTarget(pDragPos))
+ {
+ if(!GetDockAncestor()->m_TargetBottom.CheckTarget(pDragPos))
+ {
+ // Not in a docking zone, so clean up
+ NMHDR nmhdr = pDragPos->hdr;
+ CDocker* pDockDrag = (CDocker*)FromHandle(nmhdr.hwndFrom);
+ if (pDockDrag)
+ {
+ if (pDockDrag->m_BlockMove)
+ pDockDrag->RedrawWindow(0, 0, RDW_FRAME|RDW_INVALIDATE);
+
+ GetDockHint().Destroy();
+ pDockDrag->m_dwDockZone = 0;
+ pDockDrag->m_BlockMove = FALSE;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ inline BOOL CDocker::VerifyDockers()
+ // A diagnostic routine which verifies the integrity of the docking layout
+ {
+ BOOL bResult = TRUE;
+
+ // Check dock ancestor
+ std::vector<DockPtr>::iterator iter;
+
+ for (iter = GetAllDockers().begin(); iter != GetAllDockers().end(); ++iter)
+ {
+ if (GetDockAncestor() != (*iter)->m_pDockAncestor)
+ {
+ TRACE(_T("Invalid Dock Ancestor\n"));
+ bResult = FALSE;
+ }
+ }
+
+ // Check presence of dock parent
+ for (iter = GetAllDockers().begin(); iter != GetAllDockers().end(); ++iter)
+ {
+ if ((*iter)->IsUndocked() && (*iter)->m_pDockParent != 0)
+ {
+ TRACE(_T("Error: Undocked dockers should not have a dock parent\n"));
+ bResult = FALSE;
+ }
+
+ if ((*iter)->IsDocked() && (*iter)->m_pDockParent == 0)
+ {
+ TRACE(_T("Error: Docked dockers should have a dock parent\n"));
+ bResult = FALSE;
+ }
+ }
+
+ // Check dock parent/child relationship
+ for (iter = GetAllDockers().begin(); iter != GetAllDockers().end(); ++iter)
+ {
+ std::vector<CDocker*>::iterator iterChild;
+ for (iterChild = (*iter)->GetDockChildren().begin(); iterChild != (*iter)->GetDockChildren().end(); ++iterChild)
+ {
+ if ((*iterChild)->m_pDockParent != (*iter).get())
+ {
+ TRACE(_T("Error: Docking parent/Child information mismatch\n"));
+ bResult = FALSE;
+ }
+ if ((*iterChild)->GetParent() != (*iter).get())
+ {
+ TRACE(_T("Error: Incorrect windows child parent relationship\n"));
+ bResult = FALSE;
+ }
+ }
+ }
+
+ // Check dock parent chain
+ for (iter = GetAllDockers().begin(); iter != GetAllDockers().end(); ++iter)
+ {
+ CDocker* pDockTopLevel = (*iter)->GetTopmostDocker();
+ if (pDockTopLevel->IsDocked())
+ TRACE(_T("Error: Top level parent should be undocked\n"));
+ }
+
+ return bResult;
+ }
+
+ inline void CDocker::Close()
+ {
+ // Destroy the docker
+ Hide();
+ Destroy();
+ }
+
+ inline void CDocker::CloseAllDockers()
+ {
+ assert(this == GetDockAncestor()); // Must call CloseAllDockers from the DockAncestor
+
+ std::vector <DockPtr>::iterator v;
+
+ SetRedraw(FALSE);
+ std::vector<DockPtr> AllDockers = GetAllDockers();
+ for (v = AllDockers.begin(); v != AllDockers.end(); ++v)
+ {
+ // The CDocker is destroyed when the window is destroyed
+ (*v)->m_bIsClosing = TRUE;
+ (*v)->Destroy(); // Destroy the window
+ }
+
+ GetDockChildren().clear();
+ SetRedraw(TRUE);
+ RecalcDockLayout();
+ }
+
+ inline void CDocker::CloseAllTargets()
+ {
+ GetDockAncestor()->m_TargetCentre.Destroy();
+ GetDockAncestor()->m_TargetLeft.Destroy();
+ GetDockAncestor()->m_TargetTop.Destroy();
+ GetDockAncestor()->m_TargetRight.Destroy();
+ GetDockAncestor()->m_TargetBottom.Destroy();
+ }
+
+ inline void CDocker::Dock(CDocker* pDocker, UINT DockStyle)
+ // Docks the specified docker inside this docker
+ {
+ assert(pDocker);
+
+ pDocker->m_pDockParent = this;
+ pDocker->m_BlockMove = FALSE;
+ pDocker->SetDockStyle(DockStyle);
+ m_vDockChildren.push_back(pDocker);
+ pDocker->ConvertToChild(m_hWnd);
+
+ // Limit the docked size to half the parent's size if it won't fit inside parent
+ if (((DockStyle & 0xF) == DS_DOCKED_LEFT) || ((DockStyle &0xF) == DS_DOCKED_RIGHT))
+ {
+ int Width = GetDockClient().GetWindowRect().Width();
+ int BarWidth = pDocker->GetBarWidth();
+ if (pDocker->m_DockStartSize >= (Width - BarWidth))
+ pDocker->SetDockSize(MAX(Width/2 - BarWidth, BarWidth));
+
+ pDocker->m_DockSizeRatio = ((double)pDocker->m_DockStartSize) / (double)GetWindowRect().Width();
+ }
+ else
+ {
+ int Height = GetDockClient().GetWindowRect().Height();
+ int BarWidth = pDocker->GetBarWidth();
+ if (pDocker->m_DockStartSize >= (Height - BarWidth))
+ pDocker->SetDockSize(MAX(Height/2 - BarWidth, BarWidth));
+
+ pDocker->m_DockSizeRatio = ((double)pDocker->m_DockStartSize) / (double)GetWindowRect().Height();
+ }
+
+ // Redraw the docked windows
+ GetAncestor()->SetForegroundWindow();
+ GetTopmostDocker()->m_hOldFocus = pDocker->GetView()->GetHwnd();
+ pDocker->GetView()->SetFocus();
+
+ GetTopmostDocker()->SetRedraw(FALSE);
+ RecalcDockLayout();
+ GetTopmostDocker()->SetRedraw(TRUE);
+ GetTopmostDocker()->RedrawWindow();
+ }
+
+ inline void CDocker::DockInContainer(CDocker* pDock, DWORD dwDockStyle)
+ // Add a container to an existing container
+ {
+ if ((dwDockStyle & DS_DOCKED_CONTAINER) && (dynamic_cast<CDockContainer*>(pDock->GetView())))
+ {
+ // Transfer any dock children to this docker
+ pDock->MoveDockChildren(this);
+
+ // Transfer container children to the target container
+ CDockContainer* pContainer = (CDockContainer*)GetView();
+ CDockContainer* pContainerSource = (CDockContainer*)pDock->GetView();
+
+ if (pContainerSource->GetAllContainers().size() > 1)
+ {
+ // The container we're about to add has children, so transfer those first
+ std::vector<ContainerInfo>::reverse_iterator riter;
+ std::vector<ContainerInfo> AllContainers = pContainerSource->GetAllContainers();
+ for ( riter = AllContainers.rbegin() ; riter < AllContainers.rend() -1; ++riter )
+ {
+ // Remove child container from pContainerSource
+ CDockContainer* pContainerChild = (*riter).pContainer;
+ pContainerChild->ShowWindow(SW_HIDE);
+ pContainerSource->RemoveContainer(pContainerChild);
+
+ // Add child container to this container
+ pContainer->AddContainer(pContainerChild);
+
+ CDocker* pDockChild = GetDockFromView(pContainerChild);
+ pDockChild->SetParent(this);
+ pDockChild->m_pDockParent = this;
+ }
+ }
+
+ pContainer->AddContainer((CDockContainer*)pDock->GetView());
+ pDock->m_pDockParent = this;
+ pDock->m_BlockMove = FALSE;
+ pDock->ShowWindow(SW_HIDE);
+ pDock->SetWindowLongPtr(GWL_STYLE, WS_CHILD);
+ pDock->SetDockStyle(dwDockStyle);
+ pDock->SetParent(this);
+ }
+ }
+
+ inline void CDocker::DockOuter(CDocker* pDocker, DWORD dwDockStyle)
+ // Docks the specified docker inside the dock ancestor
+ {
+ assert(pDocker);
+
+ pDocker->m_pDockParent = GetDockAncestor();
+
+ DWORD OuterDocking = dwDockStyle & 0xF0000;
+ DWORD DockSide = OuterDocking / 0x10000;
+ dwDockStyle &= 0xFFF0FFFF;
+ dwDockStyle |= DockSide;
+
+ // Set the dock styles
+ DWORD dwStyle = WS_CHILD | WS_VISIBLE;
+ pDocker->m_BlockMove = FALSE;
+ pDocker->SetWindowLongPtr(GWL_STYLE, dwStyle);
+ pDocker->ShowWindow(SW_HIDE);
+ pDocker->SetDockStyle(dwDockStyle);
+
+ // Set the docking relationships
+ std::vector<CDocker*>::iterator iter = GetDockAncestor()->m_vDockChildren.begin();
+ GetDockAncestor()->m_vDockChildren.insert(iter, pDocker);
+ pDocker->SetParent(GetDockAncestor());
+ pDocker->GetDockBar().SetParent(GetDockAncestor());
+
+ // Limit the docked size to half the parent's size if it won't fit inside parent
+ if (((dwDockStyle & 0xF) == DS_DOCKED_LEFT) || ((dwDockStyle &0xF) == DS_DOCKED_RIGHT))
+ {
+ int Width = GetDockAncestor()->GetDockClient().GetWindowRect().Width();
+ int BarWidth = pDocker->GetBarWidth();
+ if (pDocker->m_DockStartSize >= (Width - BarWidth))
+ pDocker->SetDockSize(MAX(Width/2 - BarWidth, BarWidth));
+
+ pDocker->m_DockSizeRatio = ((double)pDocker->m_DockStartSize) / (double)GetDockAncestor()->GetWindowRect().Width();
+ }
+ else
+ {
+ int Height = GetDockAncestor()->GetDockClient().GetWindowRect().Height();
+ int BarWidth = pDocker->GetBarWidth();
+ if (pDocker->m_DockStartSize >= (Height - BarWidth))
+ pDocker->SetDockSize(MAX(Height/2 - BarWidth, BarWidth));
+
+ pDocker->m_DockSizeRatio = ((double)pDocker->m_DockStartSize) / (double)GetDockAncestor()->GetWindowRect().Height();
+ }
+
+ // Redraw the docked windows
+ GetAncestor()->SetFocus();
+ pDocker->GetView()->SetFocus();
+ RecalcDockLayout();
+ }
+
+ inline void CDocker::DrawAllCaptions()
+ {
+ std::vector<DockPtr>::iterator iter;
+ for (iter = GetAllDockers().begin(); iter != GetAllDockers().end(); iter++)
+ {
+ if ((*iter)->IsDocked())
+ (*iter)->GetDockClient().DrawCaption((WPARAM)1);
+ }
+ }
+
+ inline void CDocker::DrawHashBar(HWND hBar, POINT Pos)
+ // Draws a hashed bar while the splitter bar is being dragged
+ {
+ CDocker* pDock = ((CDockBar*)FromHandle(hBar))->GetDock();
+ if (NULL == pDock) return;
+
+ BOOL bVertical = ((pDock->GetDockStyle() & 0xF) == DS_DOCKED_LEFT) || ((pDock->GetDockStyle() & 0xF) == DS_DOCKED_RIGHT);
+
+ CClientDC dcBar(this);
+
+ WORD HashPattern[] = {0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA};
+ CBitmap bmHash;
+ CBrush brDithered;
+ bmHash.CreateBitmap(8, 8, 1, 1, HashPattern);
+ brDithered.CreatePatternBrush(&bmHash);
+ dcBar.SelectObject(&brDithered);
+
+ CRect rc = FromHandle(hBar)->GetWindowRect();
+ ScreenToClient(rc);
+ int cx = rc.Width();
+ int cy = rc.Height();
+ int BarWidth = pDock->GetDockBar().GetWidth();
+
+ if (bVertical)
+ dcBar.PatBlt(Pos.x - BarWidth/2, rc.top, BarWidth, cy, PATINVERT);
+ else
+ dcBar.PatBlt(rc.left, Pos.y - BarWidth/2, cx, BarWidth, PATINVERT);
+ }
+
+ inline CDockContainer* CDocker::GetContainer() const
+ {
+ CDockContainer* pContainer = NULL;
+ if (dynamic_cast<CDockContainer*>(GetView()))
+ pContainer = (CDockContainer*)GetView();
+
+ return pContainer;
+ }
+
+ inline CDocker* CDocker::GetActiveDocker() const
+ // Returns the docker whose child window has focus
+ {
+ CWnd* pWnd = GetFocus();
+ CDocker* pDock= NULL;
+ while (pWnd && (pDock == NULL))
+ {
+ if (IsRelated(pWnd))
+ pDock = (CDocker*)pWnd;
+
+ pWnd = pWnd->GetParent();
+ }
+
+ return pDock;
+ }
+
+ inline CDocker* CDocker::GetDockAncestor() const
+ // The GetDockAncestor function retrieves the pointer to the
+ // ancestor (root docker parent) of the Docker.
+ {
+ return m_pDockAncestor;
+ }
+
+ inline CDocker* CDocker::GetDockFromPoint(POINT pt) const
+ // Retrieves the Docker whose view window contains the specified point
+ {
+ // Step 1: Find the top level Docker the point is over
+ CDocker* pDockTop = NULL;
+ CWnd* pAncestor = GetDockAncestor()->GetAncestor();
+
+ // Iterate through all top level windows
+ CWnd* pWnd = GetWindow(GW_HWNDFIRST);
+ while(pWnd)
+ {
+ if (IsRelated(pWnd) || pWnd == pAncestor)
+ {
+ CDocker* pDockTest;
+ if (pWnd == pAncestor)
+ pDockTest = GetDockAncestor();
+ else
+ pDockTest = (CDocker*)pWnd;
+
+ CRect rc = pDockTest->GetClientRect();
+ pDockTest->ClientToScreen(rc);
+ if ((this != pDockTest) && rc.PtInRect(pt))
+ {
+ pDockTop = pDockTest;
+ break;
+ }
+ }
+
+ pWnd = pWnd->GetWindow(GW_HWNDNEXT);
+ }
+
+ // Step 2: Find the docker child whose view window has the point
+ CDocker* pDockTarget = NULL;
+ if (pDockTop)
+ {
+ CDocker* pDockParent = pDockTop;
+ CDocker* pDockTest = pDockParent;
+
+ while (IsRelated(pDockTest))
+ {
+ pDockParent = pDockTest;
+ CPoint ptLocal = pt;
+ pDockParent->ScreenToClient(ptLocal);
+ pDockTest = (CDocker*)pDockParent->ChildWindowFromPoint(ptLocal);
+ assert (pDockTest != pDockParent);
+ }
+
+ CRect rc = pDockParent->GetDockClient().GetWindowRect();
+ if (rc.PtInRect(pt)) pDockTarget = pDockParent;
+ }
+
+ return pDockTarget;
+ }
+
+ inline CDocker* CDocker::GetDockFromID(int n_DockID) const
+ {
+ std::vector <DockPtr>::iterator v;
+
+ if (GetDockAncestor())
+ {
+ for (v = GetDockAncestor()->m_vAllDockers.begin(); v != GetDockAncestor()->m_vAllDockers.end(); v++)
+ {
+ if (n_DockID == (*v)->GetDockID())
+ return (*v).get();
+ }
+ }
+
+ return 0;
+ }
+
+ inline CDocker* CDocker::GetDockFromView(CWnd* pView) const
+ {
+ CDocker* pDock = 0;
+ std::vector<DockPtr>::iterator iter;
+ std::vector<DockPtr> AllDockers = GetAllDockers();
+ for (iter = AllDockers.begin(); iter != AllDockers.end(); ++iter)
+ {
+ if ((*iter)->GetView() == pView)
+ pDock = (*iter).get();
+ }
+
+ return pDock;
+ }
+
+ inline int CDocker::GetDockSize() const
+ {
+ // Returns the size of the docker to be used if it is redocked
+ // Note: This function returns 0 if the docker has the DS_DOCKED_CONTAINER style
+
+ CRect rcParent;
+ if (GetDockParent())
+ rcParent = GetDockParent()->GetWindowRect();
+ else
+ rcParent = GetDockAncestor()->GetWindowRect();
+
+ double DockSize = 0;
+ if ((GetDockStyle() & DS_DOCKED_LEFT) || (GetDockStyle() & DS_DOCKED_RIGHT))
+ DockSize = (double)(rcParent.Width()*m_DockSizeRatio);
+ else if ((GetDockStyle() & DS_DOCKED_TOP) || (GetDockStyle() & DS_DOCKED_BOTTOM))
+ DockSize = (double)(rcParent.Height()*m_DockSizeRatio);
+ else if ((GetDockStyle() & DS_DOCKED_CONTAINER))
+ DockSize = 0;
+
+ return (int)DockSize;
+ }
+
+ inline CDocker* CDocker::GetTopmostDocker() const
+ // Returns the docker's parent at the top of the Z order.
+ // Could be the dock ancestor or an undocked docker.
+ {
+ CDocker* pDockTopLevel = (CDocker* const)this;
+
+ while(pDockTopLevel->GetDockParent())
+ {
+ assert (pDockTopLevel != pDockTopLevel->GetDockParent());
+ pDockTopLevel = pDockTopLevel->GetDockParent();
+ }
+
+ return pDockTopLevel;
+ }
+
+ inline CTabbedMDI* CDocker::GetTabbedMDI() const
+ {
+ CTabbedMDI* pTabbedMDI = NULL;
+ if (dynamic_cast<CTabbedMDI*>(GetView()))
+ pTabbedMDI = (CTabbedMDI*)GetView();
+
+ return pTabbedMDI;
+ }
+
+ inline int CDocker::GetTextHeight()
+ {
+ NONCLIENTMETRICS nm = {0};
+ nm.cbSize = GetSizeofNonClientMetrics();
+ SystemParametersInfo (SPI_GETNONCLIENTMETRICS, 0, &nm, 0);
+ LOGFONT lf = nm.lfStatusFont;
+
+ CClientDC dc(this);
+ dc.CreateFontIndirect(&lf);
+ CSize szText = dc.GetTextExtentPoint32(_T("Text"), lstrlen(_T("Text")));
+ return szText.cy;
+ }
+
+ inline void CDocker::Hide()
+ {
+ // Undocks a docker (if needed) and hides it.
+ // Do unhide the docker, dock it.
+
+ if (IsDocked())
+ {
+ if (dynamic_cast<CDockContainer*>(GetView()))
+ {
+ CDockContainer* pContainer = GetContainer();
+ CDocker* pDock = GetDockFromView(pContainer->GetContainerParent());
+ pDock->UndockContainer(pContainer, GetCursorPos(), FALSE);
+ }
+ else
+ {
+ CDocker* pDockUndockedFrom = SeparateFromDock();
+ pDockUndockedFrom->RecalcDockLayout();
+ }
+ }
+
+ ShowWindow(SW_HIDE);
+ }
+
+ inline BOOL CDocker::IsChildOfDocker(CWnd* pWnd) const
+ // returns true if the specified window is a child of this docker
+ {
+ while ((pWnd != NULL) && (pWnd != GetDockAncestor()))
+ {
+ if (pWnd == (CWnd*)this) return TRUE;
+ if (IsRelated(pWnd)) break;
+ pWnd = pWnd->GetParent();
+ }
+
+ return FALSE;
+ }
+
+ inline BOOL CDocker::IsDocked() const
+ {
+ return (((m_DockStyle&0xF) || (m_DockStyle & DS_DOCKED_CONTAINER)) && !m_Undocking); // Boolean expression
+ }
+
+ inline BOOL CDocker::IsDragAutoResize()
+ {
+ return m_bDragAutoResize;
+ }
+
+ inline BOOL CDocker::IsRelated(CWnd* pWnd) const
+ // Returns TRUE if the hWnd is a docker within this dock family
+ {
+ if (GetDockAncestor() == pWnd) return TRUE;
+
+ std::vector<DockPtr>::iterator iter;
+ for (iter = GetAllDockers().begin(); iter < GetAllDockers().end(); ++iter)
+ {
+ if ((*iter).get() == pWnd) return TRUE;
+ }
+
+ return FALSE;
+ }
+
+ inline BOOL CDocker::IsUndocked() const
+ {
+ return (!((m_DockStyle&0xF)|| (m_DockStyle & DS_DOCKED_CONTAINER)) && !m_Undocking); // Boolean expression
+ }
+
+ inline BOOL CDocker::LoadRegistrySettings(tString tsRegistryKeyName)
+ // Recreates the docker layout based on information stored in the registry.
+ // Assumes the DockAncestor window is already created.
+ {
+ BOOL bResult = FALSE;
+
+ if (0 != tsRegistryKeyName.size())
+ {
+ std::vector<DockInfo> vDockList;
+ std::vector<int> vActiveContainers;
+ tString tsKey = _T("Software\\") + tsRegistryKeyName + _T("\\Dock Windows");
+ HKEY hKey = 0;
+ RegOpenKeyEx(HKEY_CURRENT_USER, tsKey.c_str(), 0, KEY_READ, &hKey);
+ if (hKey)
+ {
+ DWORD dwType = REG_BINARY;
+ DWORD BufferSize = sizeof(DockInfo);
+ DockInfo di;
+ int i = 0;
+ TCHAR szNumber[20];
+ tString tsSubKey = _T("DockChild");
+ tsSubKey += _itot(i, szNumber, 10);
+
+ // Fill the DockList vector from the registry
+ while (0 == RegQueryValueEx(hKey, tsSubKey.c_str(), NULL, &dwType, (LPBYTE)&di, &BufferSize))
+ {
+ vDockList.push_back(di);
+ i++;
+ tsSubKey = _T("DockChild");
+ tsSubKey += _itot(i, szNumber, 10);
+ }
+
+ dwType = REG_DWORD;
+ BufferSize = sizeof(int);
+ int nID;
+ i = 0;
+ tsSubKey = _T("ActiveContainer");
+ tsSubKey += _itot(i, szNumber, 10);
+ // Fill the DockList vector from the registry
+ while (0 == RegQueryValueEx(hKey, tsSubKey.c_str(), NULL, &dwType, (LPBYTE)&nID, &BufferSize))
+ {
+ vActiveContainers.push_back(nID);
+ i++;
+ tsSubKey = _T("ActiveContainer");
+ tsSubKey += _itot(i, szNumber, 10);
+ }
+
+ RegCloseKey(hKey);
+ if (vDockList.size() > 0) bResult = TRUE;
+ }
+
+ // Add dockers without parents first
+ std::vector<DockInfo>::iterator iter;
+ for (iter = vDockList.begin(); iter < vDockList.end() ; ++iter)
+ {
+ DockInfo di = (*iter);
+ if (di.DockParentID == 0)
+ {
+ CDocker* pDocker = NewDockerFromID(di.DockID);
+ if (pDocker)
+ {
+ if (di.DockStyle & 0xF)
+ AddDockedChild(pDocker, di.DockStyle, di.DockSize, di.DockID);
+ else
+ AddUndockedChild(pDocker, di.DockStyle, di.DockSize, di.Rect, di.DockID);
+ }
+ else
+ {
+ TRACE(_T("Failed to add dockers without parents from registry"));
+ bResult = FALSE;
+ }
+ }
+ }
+
+ // Remove dockers without parents from vDockList
+ for (UINT n = (UINT)vDockList.size(); n > 0; --n)
+ {
+ iter = vDockList.begin() + n-1;
+ if ((*iter).DockParentID == 0)
+ vDockList.erase(iter);
+ }
+
+ // Add remaining dockers
+ while (vDockList.size() > 0)
+ {
+ bool bFound = false;
+ std::vector<DockInfo>::iterator iter;
+ for (iter = vDockList.begin(); iter < vDockList.end(); ++iter)
+ {
+ DockInfo di = *iter;
+ CDocker* pDockParent = GetDockFromID(di.DockParentID);
+
+ if (pDockParent != 0)
+ {
+ CDocker* pDock = NewDockerFromID(di.DockID);
+ if(pDock)
+ {
+ pDockParent->AddDockedChild(pDock, di.DockStyle, di.DockSize, di.DockID);
+ bFound = true;
+ }
+ else
+ {
+ TRACE(_T("Failed to add dockers with parents from registry"));
+ bResult = FALSE;
+ }
+
+ vDockList.erase(iter);
+ break;
+ }
+ }
+
+ if (!bFound)
+ {
+ TRACE(_T("Orphaned dockers stored in registry "));
+ bResult = FALSE;
+ break;
+ }
+ }
+
+ std::vector<int>::iterator iterID;
+ for (iterID = vActiveContainers.begin(); iterID < vActiveContainers.end(); ++iterID)
+ {
+ CDocker* pDocker = GetDockFromID(*iterID);
+ if (pDocker)
+ {
+ CDockContainer* pContainer = pDocker->GetContainer();
+ if (pContainer)
+ {
+ int nPage = pContainer->GetContainerIndex(pContainer);
+ if (nPage >= 0)
+ pContainer->SelectPage(nPage);
+ }
+ }
+ }
+ }
+
+ if (!bResult) CloseAllDockers();
+ return bResult;
+ }
+
+ inline void CDocker::MoveDockChildren(CDocker* pDockTarget)
+ // Used internally by Dock and Undock
+ {
+ assert(pDockTarget);
+
+ // Transfer any dock children from the current docker to the target docker
+ std::vector<CDocker*>::iterator iter;
+ for (iter = GetDockChildren().begin(); iter < GetDockChildren().end(); ++iter)
+ {
+ pDockTarget->GetDockChildren().push_back(*iter);
+ (*iter)->m_pDockParent = pDockTarget;
+ (*iter)->SetParent(pDockTarget);
+ (*iter)->GetDockBar().SetParent(pDockTarget);
+ }
+ GetDockChildren().clear();
+ }
+
+ inline CDocker* CDocker::NewDockerFromID(int nID)
+ // Used in LoadRegistrySettings. Creates a new Docker from the specified ID
+ {
+ UNREFERENCED_PARAMETER(nID);
+
+ // Override this function to create the Docker objects as shown below
+
+ CDocker* pDock = NULL;
+ /* switch(nID)
+ {
+ case ID_CLASSES:
+ pDock = new CDockClasses;
+ break;
+ case ID_FILES:
+ pDock = new CDockFiles;
+ break;
+ default:
+ TRACE(_T("Unknown Dock ID\n"));
+ break;
+ } */
+
+ return pDock;
+ }
+
+ inline void CDocker::OnActivate(WPARAM wParam, LPARAM lParam)
+ {
+ UNREFERENCED_PARAMETER(lParam);
+
+ // Only top level undocked dockers get this message
+ if (LOWORD(wParam) == WA_INACTIVE)
+ {
+ GetTopmostDocker()->m_hOldFocus = ::GetFocus();
+
+ // Send a notification of focus lost
+ int idCtrl = ::GetDlgCtrlID(m_hOldFocus);
+ NMHDR nhdr={0};
+ nhdr.hwndFrom = m_hOldFocus;
+ nhdr.idFrom = idCtrl;
+ nhdr.code = UWM_FRAMELOSTFOCUS;
+ SendMessage(WM_NOTIFY, (WPARAM)idCtrl, (LPARAM)&nhdr);
+ }
+ }
+
+ inline void CDocker::OnCaptionTimer(WPARAM wParam, LPARAM lParam)
+ {
+ UNREFERENCED_PARAMETER(lParam);
+
+ if (this == GetDockAncestor())
+ {
+ if (wParam == 1)
+ {
+ DrawAllCaptions();
+ m_nTimerCount++;
+ if (m_nTimerCount == 10)
+ {
+ KillTimer(wParam);
+ m_nTimerCount = 0;
+ }
+ }
+ }
+ }
+
+ inline void CDocker::OnCreate()
+ {
+
+#if defined(WINVER) && defined (WS_EX_LAYOUTRTL) && (WINVER >= 0x0500)
+ if (GetParent()->GetWindowLongPtr(GWL_EXSTYLE) & WS_EX_LAYOUTRTL)
+ {
+ DWORD dwExStyle = GetWindowLongPtr(GWL_EXSTYLE);
+ SetWindowLongPtr(GWL_EXSTYLE, dwExStyle | WS_EX_LAYOUTRTL);
+ }
+#endif
+
+ // Create the various child windows
+ GetDockClient().SetDock(this);
+ GetDockClient().Create(this);
+
+ assert(GetView()); // Use SetView in CMainFrame's constructor to set the view window
+ GetView()->Create(&GetDockClient());
+
+ // Create the slider bar belonging to this docker
+ GetDockBar().SetDock(this);
+ if (GetDockAncestor() != this)
+ GetDockBar().Create(GetParent());
+
+ // Now remove the WS_POPUP style. It was required to allow this window
+ // to be owned by the frame window.
+ SetWindowLongPtr(GWL_STYLE, WS_CHILD);
+ SetParent(GetParent()); // Reinstate the window's parent
+
+ // Set the default colour for the splitter bar
+ COLORREF rgbColour = GetSysColor(COLOR_BTNFACE);
+ CWnd* pFrame = GetDockAncestor()->GetAncestor();
+ ReBarTheme* pTheme = (ReBarTheme*)pFrame->SendMessage(UWM_GETREBARTHEME, 0, 0);
+
+ if (pTheme && pTheme->UseThemes && pTheme->clrBkgnd2 != 0)
+ rgbColour =pTheme->clrBkgnd2;
+
+ SetBarColor(rgbColour);
+
+ // Set the caption height based on text height
+ m_NCHeight = MAX(20, GetTextHeight() + 5);
+ }
+
+ inline void CDocker::OnDestroy(WPARAM wParam, LPARAM lParam)
+ {
+ UNREFERENCED_PARAMETER(wParam);
+ UNREFERENCED_PARAMETER(lParam);
+
+ // Destroy any dock children first
+ std::vector<CDocker*>::iterator iter;
+ for (iter = GetDockChildren().begin(); iter < GetDockChildren().end(); ++iter)
+ {
+ (*iter)->Destroy();
+ }
+
+ if (dynamic_cast<CDockContainer*>(GetView()) && IsUndocked())
+ {
+ CDockContainer* pContainer = (CDockContainer*)GetView();
+ if (pContainer->GetAllContainers().size() > 1)
+ {
+ // This container has children, so destroy them now
+ std::vector<ContainerInfo> AllContainers = pContainer->GetAllContainers();
+ std::vector<ContainerInfo>::iterator iter;
+ for (iter = AllContainers.begin(); iter < AllContainers.end(); ++iter)
+ {
+ if ((*iter).pContainer != pContainer)
+ {
+ // Reset container parent before destroying the dock window
+ CDocker* pDock = GetDockFromView((*iter).pContainer);
+ if (pContainer->IsWindow())
+ pContainer->SetParent(&pDock->GetDockClient());
+
+ pDock->Destroy();
+ }
+ }
+ }
+ }
+
+ GetDockBar().Destroy();
+
+ // Post a destroy docker message
+ if ( GetDockAncestor()->IsWindow() )
+ GetDockAncestor()->PostMessage(UWM_DOCK_DESTROYED, (WPARAM)this, 0L);
+ }
+
+ inline void CDocker::OnDockDestroyed(WPARAM wParam, LPARAM lParam)
+ {
+ UNREFERENCED_PARAMETER(lParam);
+
+ CDocker* pDock = (CDocker*)wParam;
+
+ assert( this == GetDockAncestor() );
+ std::vector<DockPtr>::iterator iter;
+ for (iter = GetAllDockers().begin(); iter < GetAllDockers().end(); ++iter)
+ {
+ if ((*iter).get() == pDock)
+ {
+ GetAllDockers().erase(iter);
+ break;
+ }
+ }
+ }
+
+ inline void CDocker::OnExitSizeMove(WPARAM wParam, LPARAM lParam)
+ {
+ UNREFERENCED_PARAMETER(wParam);
+ UNREFERENCED_PARAMETER(lParam);
+
+ m_BlockMove = FALSE;
+ m_bIsDragging = FALSE;
+ SendNotify(UWM_DOCK_END);
+ }
+
+ inline LRESULT CDocker::OnNotify(WPARAM wParam, LPARAM lParam)
+ {
+ UNREFERENCED_PARAMETER(wParam);
+ LPDRAGPOS pdp = (LPDRAGPOS)lParam;
+
+ switch (((LPNMHDR)lParam)->code)
+ {
+ case UWM_DOCK_START:
+ {
+ if (IsDocked())
+ {
+ Undock(GetCursorPos());
+ SendMessage(WM_NCLBUTTONDOWN, HTCAPTION, MAKELPARAM(pdp->ptPos.x, pdp->ptPos.y));
+ }
+ }
+ break;
+
+ case UWM_DOCK_MOVE:
+ {
+ CheckAllTargets((LPDRAGPOS)lParam);
+ }
+ break;
+
+ case UWM_DOCK_END:
+ {
+ CDocker* pDock = (CDocker*)FromHandle(pdp->hdr.hwndFrom);
+ if (NULL == pDock) break;
+
+ UINT DockZone = pdp->DockZone;
+ CRect rc = pDock->GetWindowRect();
+
+ switch(DockZone)
+ {
+ case DS_DOCKED_LEFT:
+ case DS_DOCKED_RIGHT:
+ pDock->SetDockSize(rc.Width());
+ Dock(pDock, pDock->GetDockStyle() | DockZone);
+ break;
+ case DS_DOCKED_TOP:
+ case DS_DOCKED_BOTTOM:
+ pDock->SetDockSize(rc.Height());
+ Dock(pDock, pDock->GetDockStyle() | DockZone);
+ break;
+ case DS_DOCKED_CONTAINER:
+ {
+ DockInContainer(pDock, pDock->GetDockStyle() | DockZone);
+ CDockContainer* pContainer = (CDockContainer*)GetView();
+ int nPage = pContainer->GetContainerIndex((CDockContainer*)pDock->GetView());
+ pContainer->SelectPage(nPage);
+ }
+ break;
+ case DS_DOCKED_LEFTMOST:
+ case DS_DOCKED_RIGHTMOST:
+ pDock->SetDockSize(rc.Width());
+ DockOuter(pDock, pDock->GetDockStyle() | DockZone);
+ break;
+ case DS_DOCKED_TOPMOST:
+ case DS_DOCKED_BOTTOMMOST:
+ pDock->SetDockSize(rc.Height());
+ DockOuter(pDock, pDock->GetDockStyle() | DockZone);
+ break;
+ }
+
+ GetDockHint().Destroy();
+ CloseAllTargets();
+ }
+ break;
+
+ case UWM_BAR_START:
+ {
+ CPoint pt = pdp->ptPos;
+ ScreenToClient(pt);
+ if (!IsDragAutoResize())
+ DrawHashBar(pdp->hdr.hwndFrom, pt);
+ m_OldPoint = pt;
+ }
+ break;
+
+ case UWM_BAR_MOVE:
+ {
+ CPoint pt = pdp->ptPos;
+ ScreenToClient(pt);
+
+ if (pt != m_OldPoint)
+ {
+ if (IsDragAutoResize())
+ ResizeDockers(pdp);
+ else
+ {
+ DrawHashBar(pdp->hdr.hwndFrom, m_OldPoint);
+ DrawHashBar(pdp->hdr.hwndFrom, pt);
+ }
+
+ m_OldPoint = pt;
+ }
+ }
+ break;
+
+ case UWM_BAR_END:
+ {
+ POINT pt = pdp->ptPos;
+ ScreenToClient(pt);
+
+ if (!IsDragAutoResize())
+ DrawHashBar(pdp->hdr.hwndFrom, pt);
+
+ ResizeDockers(pdp);
+ }
+ break;
+ case NM_SETFOCUS:
+ if (GetDockAncestor()->IsWindow())
+ GetDockAncestor()->PostMessage(UWM_DOCK_ACTIVATED, 0, 0);
+ break;
+ case UWM_FRAMEGOTFOCUS:
+ if (GetDockAncestor()->IsWindow())
+ GetDockAncestor()->PostMessage(UWM_DOCK_ACTIVATED, 0, 0);
+ if (GetView()->IsWindow())
+ GetView()->SendMessage(WM_NOTIFY, wParam, lParam);
+ break;
+ case UWM_FRAMELOSTFOCUS:
+ if (GetDockAncestor()->IsWindow())
+ GetDockAncestor()->PostMessage(UWM_DOCK_ACTIVATED, 0, 0);
+ if (GetView()->IsWindow())
+ GetView()->SendMessage(WM_NOTIFY, wParam, lParam);
+ break;
+ }
+ return 0L;
+ }
+
+ inline void CDocker::ResizeDockers(LPDRAGPOS pdp)
+ // Called when the docker's splitter bar is dragged
+ {
+ assert(pdp);
+
+ POINT pt = pdp->ptPos;
+ ScreenToClient(pt);
+
+ CDocker* pDock = ((CDockBar*)FromHandle(pdp->hdr.hwndFrom))->GetDock();
+ if (NULL == pDock) return;
+
+ RECT rcDock = pDock->GetWindowRect();
+ ScreenToClient(rcDock);
+
+ double dBarWidth = pDock->GetDockBar().GetWidth();
+ int iBarWidth = pDock->GetDockBar().GetWidth();
+ int DockSize;
+
+ switch (pDock->GetDockStyle() & 0xF)
+ {
+ case DS_DOCKED_LEFT:
+ DockSize = MAX(pt.x, iBarWidth/2) - rcDock.left - (int)(.5* dBarWidth);
+ DockSize = MAX(-iBarWidth, DockSize);
+ pDock->SetDockSize(DockSize);
+ pDock->m_DockSizeRatio = ((double)pDock->m_DockStartSize)/((double)pDock->m_pDockParent->GetWindowRect().Width());
+ break;
+ case DS_DOCKED_RIGHT:
+ DockSize = rcDock.right - MAX(pt.x, iBarWidth/2) - (int)(.5* dBarWidth);
+ DockSize = MAX(-iBarWidth, DockSize);
+ pDock->SetDockSize(DockSize);
+ pDock->m_DockSizeRatio = ((double)pDock->m_DockStartSize)/((double)pDock->m_pDockParent->GetWindowRect().Width());
+ break;
+ case DS_DOCKED_TOP:
+ DockSize = MAX(pt.y, iBarWidth/2) - rcDock.top - (int)(.5* dBarWidth);
+ DockSize = MAX(-iBarWidth, DockSize);
+ pDock->SetDockSize(DockSize);
+ pDock->m_DockSizeRatio = ((double)pDock->m_DockStartSize)/((double)pDock->m_pDockParent->GetWindowRect().Height());
+ break;
+ case DS_DOCKED_BOTTOM:
+ DockSize = rcDock.bottom - MAX(pt.y, iBarWidth/2) - (int)(.5* dBarWidth);
+ DockSize = MAX(-iBarWidth, DockSize);
+ pDock->SetDockSize(DockSize);
+ pDock->m_DockSizeRatio = ((double)pDock->m_DockStartSize)/((double)pDock->m_pDockParent->GetWindowRect().Height());
+ break;
+ }
+
+ RecalcDockLayout();
+ }
+
+ inline void CDocker::OnSetFocus(WPARAM wParam, LPARAM lParam)
+ {
+ UNREFERENCED_PARAMETER(wParam);
+ UNREFERENCED_PARAMETER(lParam);
+
+ if (IsUndocked() && m_hOldFocus)
+ ::SetFocus(m_hOldFocus);
+ else
+ // Pass focus on the the view window
+ GetView()->SetFocus();
+
+ if ((this == GetTopmostDocker()) && (this != GetDockAncestor()))
+ {
+ // Send a notification to top level window
+ int idCtrl = ::GetDlgCtrlID(m_hOldFocus);
+ NMHDR nhdr={0};
+ nhdr.hwndFrom = m_hOldFocus;
+ nhdr.idFrom = idCtrl;
+ nhdr.code = NM_SETFOCUS;
+ SendMessage(WM_NOTIFY, (WPARAM)idCtrl, (LPARAM)&nhdr);
+ }
+ }
+
+ inline void CDocker::OnSysColorChange(WPARAM wParam, LPARAM lParam)
+ {
+ UNREFERENCED_PARAMETER(wParam);
+ UNREFERENCED_PARAMETER(lParam);
+
+ if (this == GetDockAncestor())
+ {
+ COLORREF rgbColour = GetSysColor(COLOR_BTNFACE);
+ CWnd* pFrame = GetDockAncestor()->GetAncestor();
+ ReBarTheme* pTheme = (ReBarTheme*)pFrame->SendMessage(UWM_GETREBARTHEME, 0, 0);
+
+ if (pTheme && pTheme->UseThemes && pTheme->clrBand2 != 0)
+ rgbColour = pTheme->clrBkgnd2;
+ else
+ rgbColour = GetSysColor(COLOR_BTNFACE);
+
+ // Set the splitter bar colour for each docker decendant
+ std::vector<DockPtr>::iterator iter;
+ for (iter = GetAllDockers().begin(); iter < GetAllDockers().end(); ++iter)
+ (*iter)->SetBarColor(rgbColour);
+
+ // Set the splitter bar colour for the docker ancestor
+ SetBarColor(rgbColour);
+ }
+ }
+
+ inline LRESULT CDocker::OnSysCommand(WPARAM wParam, LPARAM lParam)
+ {
+ switch(wParam&0xFFF0)
+ {
+ case SC_MOVE:
+ // An undocked docker is being moved
+ {
+ BOOL bResult = FALSE;
+ m_bIsDragging = TRUE;
+ SetCursor(LoadCursor(NULL, IDC_ARROW));
+
+ if (SystemParametersInfo(SPI_GETDRAGFULLWINDOWS, 0, &bResult, 0))
+ {
+ // Turn on DragFullWindows for this move
+ SystemParametersInfo(SPI_SETDRAGFULLWINDOWS, TRUE, 0, 0);
+
+ // Process this message
+ DefWindowProc(WM_SYSCOMMAND, wParam, lParam);
+
+ // Return DragFullWindows to its previous state
+ SystemParametersInfo(SPI_SETDRAGFULLWINDOWS, bResult, 0, 0);
+ return 0L;
+ }
+ }
+ break;
+ case SC_CLOSE:
+ // The close button is pressed on an undocked docker
+ m_bIsClosing = TRUE;
+ break;
+ }
+ return CWnd::WndProcDefault(WM_SYSCOMMAND, wParam, lParam);
+ }
+
+ inline LRESULT CDocker::OnWindowPosChanging(WPARAM wParam, LPARAM lParam)
+ {
+ // Suspend dock drag moving while over dock zone
+ if (m_BlockMove)
+ {
+ LPWINDOWPOS pWndPos = (LPWINDOWPOS)lParam;
+ pWndPos->flags |= SWP_NOMOVE|SWP_FRAMECHANGED;
+ return 0;
+ }
+
+ return CWnd::WndProcDefault(WM_WINDOWPOSCHANGING, wParam, lParam);
+ }
+
+ inline void CDocker::OnWindowPosChanged(WPARAM wParam, LPARAM lParam)
+ {
+ UNREFERENCED_PARAMETER(wParam);
+
+ if (m_bIsDragging)
+ {
+ // Send a Move notification to the parent
+ if ( IsLeftButtonDown() )
+ {
+ LPWINDOWPOS wPos = (LPWINDOWPOS)lParam;
+ if ((!(wPos->flags & SWP_NOMOVE)) || m_BlockMove)
+ SendNotify(UWM_DOCK_MOVE);
+ }
+ else
+ {
+ CloseAllTargets();
+ m_BlockMove = FALSE;
+ }
+ }
+ else if (this == GetTopmostDocker())
+ {
+ // Reposition the dock children
+ if (IsUndocked() && IsWindowVisible() && !m_bIsClosing) RecalcDockLayout();
+ }
+ }
+
+ inline void CDocker::PreCreate(CREATESTRUCT &cs)
+ {
+ // Specify the WS_POPUP style to have this window owned
+ if (this != GetDockAncestor())
+ cs.style = WS_POPUP;
+
+ cs.dwExStyle = WS_EX_TOOLWINDOW;
+ }
+
+ inline void CDocker::PreRegisterClass(WNDCLASS &wc)
+ {
+ wc.lpszClassName = _T("Win32++ Docker");
+ wc.hCursor = ::LoadCursor(NULL, IDC_ARROW);
+ }
+
+ inline void CDocker::RecalcDockChildLayout(CRect rc)
+ {
+ // This function positions the Docker's dock children, the Dockers client area
+ // and draws the dockbar bars.
+
+ // Notes:
+ // 1) This function is called recursively.
+ // 2) The client area and child dockers are positioned simultaneously with
+ // DeferWindowPos to avoid drawing errors in complex docker arrangements.
+ // 3) The docker's client area contains the docker's caption (if any) and the docker's view window.
+
+ // Note: All top level dockers are undocked, including the dock ancestor.
+ if (IsDocked())
+ {
+ rc.OffsetRect(-rc.left, -rc.top);
+ }
+
+ HDWP hdwp = BeginDeferWindowPos((int)m_vDockChildren.size() +2);
+
+ // Step 1: Calculate the position of each Docker child, DockBar, and Client window.
+ // The Client area = the docker rect minus the area of dock children and the dock bar (splitter bar).
+ for (UINT u = 0; u < m_vDockChildren.size(); ++u)
+ {
+ CRect rcChild = rc;
+ double DockSize = m_vDockChildren[u]->m_DockStartSize;;
+
+ // Calculate the size of the Docker children
+ switch (m_vDockChildren[u]->GetDockStyle() & 0xF)
+ {
+ case DS_DOCKED_LEFT:
+ if (!(GetDockStyle() & DS_FIXED_RESIZE))
+ DockSize = MIN(m_vDockChildren[u]->m_DockSizeRatio*(GetWindowRect().Width()), rcChild.Width());
+ rcChild.right = rcChild.left + (int)DockSize;
+ break;
+ case DS_DOCKED_RIGHT:
+ if (!(GetDockStyle() & DS_FIXED_RESIZE))
+ DockSize = MIN(m_vDockChildren[u]->m_DockSizeRatio*(GetWindowRect().Width()), rcChild.Width());
+ rcChild.left = rcChild.right - (int)DockSize;
+ break;
+ case DS_DOCKED_TOP:
+ if (!(GetDockStyle() & DS_FIXED_RESIZE))
+ DockSize = MIN(m_vDockChildren[u]->m_DockSizeRatio*(GetWindowRect().Height()), rcChild.Height());
+ rcChild.bottom = rcChild.top + (int)DockSize;
+ break;
+ case DS_DOCKED_BOTTOM:
+ if (!(GetDockStyle() & DS_FIXED_RESIZE))
+ DockSize = MIN(m_vDockChildren[u]->m_DockSizeRatio*(GetWindowRect().Height()), rcChild.Height());
+ rcChild.top = rcChild.bottom - (int)DockSize;
+ break;
+ }
+
+ if (m_vDockChildren[u]->IsDocked())
+ {
+ // Position this docker's children
+ hdwp = m_vDockChildren[u]->DeferWindowPos(hdwp, NULL, rcChild, SWP_SHOWWINDOW|SWP_FRAMECHANGED);
+ m_vDockChildren[u]->m_rcChild = rcChild;
+
+ rc.SubtractRect(rc, rcChild);
+
+ // Calculate the dimensions of the splitter bar
+ CRect rcBar = rc;
+ DWORD DockSide = m_vDockChildren[u]->GetDockStyle() & 0xF;
+
+ if (DS_DOCKED_LEFT == DockSide) rcBar.right = rcBar.left + m_vDockChildren[u]->GetBarWidth();
+ if (DS_DOCKED_RIGHT == DockSide) rcBar.left = rcBar.right - m_vDockChildren[u]->GetBarWidth();
+ if (DS_DOCKED_TOP == DockSide) rcBar.bottom = rcBar.top + m_vDockChildren[u]->GetBarWidth();
+ if (DS_DOCKED_BOTTOM == DockSide) rcBar.top = rcBar.bottom - m_vDockChildren[u]->GetBarWidth();
+
+ // Save the splitter bar position. We will reposition it later.
+ m_vDockChildren[u]->m_rcBar = rcBar;
+ rc.SubtractRect(rc, rcBar);
+ }
+ }
+
+ // Step 2: Position the Dock client and dock bar
+ hdwp = GetDockClient().DeferWindowPos(hdwp, NULL, rc, SWP_SHOWWINDOW |SWP_FRAMECHANGED);
+ EndDeferWindowPos(hdwp);
+
+ // Position the dockbar. Only docked dockers have a dock bar.
+ if (IsDocked())
+ {
+ // The SWP_NOCOPYBITS forces a redraw of the dock bar.
+ GetDockBar().SetWindowPos(NULL, m_rcBar, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOCOPYBITS );
+ }
+
+ // Step 3: Now recurse through the docker's children. They might have children of their own.
+ for (UINT v = 0; v < m_vDockChildren.size(); ++v)
+ {
+ m_vDockChildren[v]->RecalcDockChildLayout(m_vDockChildren[v]->m_rcChild);
+ }
+ }
+
+ inline void CDocker::RecalcDockLayout()
+ // Repositions the dock children of a top level docker
+ {
+ if (GetDockAncestor()->IsWindow())
+ {
+ CRect rc = GetTopmostDocker()->GetClientRect();
+ GetTopmostDocker()->RecalcDockChildLayout(rc);
+ GetTopmostDocker()->UpdateWindow();
+ }
+ }
+
+ inline std::vector<CDocker*> CDocker::SortDockers()
+ // Returns a vector of sorted dockers, used by SaveRegistrySettings.
+ {
+ std::vector<CDocker*> vSorted;
+ std::vector<CDocker*>::iterator itSort;
+ std::vector<DockPtr>::iterator itAll;
+
+ // Add undocked top level dockers
+ for (itAll = GetAllDockers().begin(); itAll < GetAllDockers().end(); ++itAll)
+ {
+ if (!(*itAll)->GetDockParent())
+ vSorted.push_back((*itAll).get());
+ }
+
+ // Add dock ancestor's children
+ vSorted.insert(vSorted.end(), GetDockAncestor()->GetDockChildren().begin(), GetDockAncestor()->GetDockChildren().end());
+
+ // Add other dock children
+ int index = 0;
+ itSort = vSorted.begin();
+ while (itSort < vSorted.end())
+ {
+ vSorted.insert(vSorted.end(), (*itSort)->GetDockChildren().begin(), (*itSort)->GetDockChildren().end());
+ itSort = vSorted.begin() + (++index);
+ }
+
+ // Add dockers docked in containers
+ std::vector<CDocker*> vDockContainers;
+ for (itSort = vSorted.begin(); itSort< vSorted.end(); ++itSort)
+ {
+ if ((*itSort)->GetContainer())
+ vDockContainers.push_back(*itSort);
+ }
+
+ for (itSort = vDockContainers.begin(); itSort < vDockContainers.end(); ++itSort)
+ {
+ CDockContainer* pContainer = (*itSort)->GetContainer();
+
+ for (UINT i = 1; i < pContainer->GetAllContainers().size(); ++i)
+ {
+ CDockContainer* pChild = pContainer->GetContainerFromIndex(i);
+ CDocker* pDock = GetDockFromView(pChild);
+ vSorted.push_back(pDock);
+ }
+ }
+
+ return vSorted;
+ }
+
+ inline BOOL CDocker::SaveRegistrySettings(tString tsRegistryKeyName)
+ // Stores the docking configuration in the registry
+ // NOTE: This function assumes that each docker has a unique DockID
+ {
+ assert(VerifyDockers());
+
+ std::vector<CDocker*> vSorted = SortDockers();
+ std::vector<CDocker*>::iterator iter;
+ std::vector<DockInfo> vDockInfo;
+
+ if (0 != tsRegistryKeyName.size())
+ {
+ // Fill the DockInfo vector with the docking information
+ for (iter = vSorted.begin(); iter < vSorted.end(); ++iter)
+ {
+ DockInfo di = {0};
+ di.DockID = (*iter)->GetDockID();
+ di.DockStyle = (*iter)->GetDockStyle();
+ di.DockSize = (*iter)->GetDockSize();
+ di.Rect = (*iter)->GetWindowRect();
+ if ((*iter)->GetDockParent())
+ di.DockParentID = (*iter)->GetDockParent()->GetDockID();
+
+ vDockInfo.push_back(di);
+ }
+
+ tString tsKeyName = _T("Software\\") + tsRegistryKeyName;
+ HKEY hKey = NULL;
+ HKEY hKeyDock = NULL;
+
+ try
+ {
+ if (ERROR_SUCCESS != RegCreateKeyEx(HKEY_CURRENT_USER, tsKeyName.c_str(), 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, NULL))
+ throw (CWinException(_T("RegCreateKeyEx Failed")));
+
+ RegDeleteKey(hKey, _T("Dock Windows"));
+ if (ERROR_SUCCESS != RegCreateKeyEx(hKey, _T("Dock Windows"), 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKeyDock, NULL))
+ throw (CWinException(_T("RegCreateKeyEx Failed")));
+
+ // Add the Dock windows information to the registry
+ for (UINT u = 0; u < vDockInfo.size(); ++u)
+ {
+ DockInfo di = vDockInfo[u];
+ TCHAR szNumber[16];
+ tString tsSubKey = _T("DockChild");
+ tsSubKey += _itot((int)u, szNumber, 10);
+ if(ERROR_SUCCESS != RegSetValueEx(hKeyDock, tsSubKey.c_str(), 0, REG_BINARY, (LPBYTE)&di, sizeof(DockInfo)))
+ throw (CWinException(_T("RegSetValueEx failed")));
+ }
+
+ // Add Active Container to the registry
+ int i = 0;
+ for (iter = vSorted.begin(); iter < vSorted.end(); ++iter)
+ {
+ CDockContainer* pContainer = (*iter)->GetContainer();
+
+ if (pContainer && (pContainer == pContainer->GetActiveContainer()))
+ {
+ TCHAR szNumber[20];
+ tString tsSubKey = _T("ActiveContainer");
+ tsSubKey += _itot(i++, szNumber, 10);
+ int nID = GetDockFromView(pContainer)->GetDockID();
+ if(ERROR_SUCCESS != RegSetValueEx(hKeyDock, tsSubKey.c_str(), 0, REG_DWORD, (LPBYTE)&nID, sizeof(int)))
+ throw (CWinException(_T("RegSetValueEx failed")));
+ }
+ }
+
+ RegCloseKey(hKeyDock);
+ RegCloseKey(hKey);
+ }
+
+ catch (const CWinException& e)
+ {
+ // Roll back the registry changes by deleting the subkeys
+ if (hKey)
+ {
+ if (hKeyDock)
+ {
+ RegDeleteKey(hKeyDock, _T("Dock Windows"));
+ RegCloseKey(hKeyDock);
+ }
+
+ RegDeleteKey(HKEY_CURRENT_USER ,tsKeyName.c_str());
+ RegCloseKey(hKey);
+ }
+
+ e.what();
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+ }
+
+ inline void CDocker::SendNotify(UINT nMessageID)
+ // Sends a docking notification to the docker below the cursor
+ {
+ DRAGPOS DragPos;
+ DragPos.hdr.code = nMessageID;
+ DragPos.hdr.hwndFrom = m_hWnd;
+ DragPos.ptPos = GetCursorPos();
+ DragPos.DockZone = m_dwDockZone;
+ m_dwDockZone = 0;
+
+ CDocker* pDock = GetDockFromPoint(DragPos.ptPos);
+
+ if (pDock)
+ pDock->SendMessage(WM_NOTIFY, 0L, (LPARAM)&DragPos);
+ else
+ {
+ if (GetDockHint().IsWindow()) GetDockHint().Destroy();
+ CloseAllTargets();
+ m_BlockMove = FALSE;
+ }
+ }
+
+ inline void CDocker::SetDockStyle(DWORD dwDockStyle)
+ {
+ if (IsWindow())
+ {
+ if ((dwDockStyle & DS_CLIENTEDGE) != (m_DockStyle & DS_CLIENTEDGE))
+ {
+ if (dwDockStyle & DS_CLIENTEDGE)
+ {
+ DWORD dwExStyle = (DWORD)GetDockClient().GetWindowLongPtr(GWL_EXSTYLE)|WS_EX_CLIENTEDGE;
+ GetDockClient().SetWindowLongPtr(GWL_EXSTYLE, dwExStyle);
+ GetDockClient().RedrawWindow(0, 0, RDW_INVALIDATE|RDW_UPDATENOW|RDW_ERASE|RDW_FRAME);
+ }
+ else
+ {
+ DWORD dwExStyle = (DWORD)GetDockClient().GetWindowLongPtr(GWL_EXSTYLE);
+ dwExStyle &= ~WS_EX_CLIENTEDGE;
+ GetDockClient().SetWindowLongPtr(GWL_EXSTYLE, dwExStyle);
+ GetDockClient().RedrawWindow(0, 0, RDW_INVALIDATE|RDW_UPDATENOW|RDW_ERASE|RDW_FRAME);
+ }
+ }
+
+ RecalcDockLayout();
+ }
+
+ m_DockStyle = dwDockStyle;
+ }
+
+ inline void CDocker::SetCaption(LPCTSTR szCaption)
+ // Sets the caption text
+ {
+ GetDockClient().SetCaption(szCaption);
+
+ if (IsWindow())
+ SetWindowText(szCaption);
+ }
+
+ inline void CDocker::SetCaptionColors(COLORREF Foregnd1, COLORREF Backgnd1, COLORREF ForeGnd2, COLORREF BackGnd2)
+ {
+ GetDockClient().SetCaptionColors(Foregnd1, Backgnd1, ForeGnd2, BackGnd2);
+ }
+
+ inline void CDocker::SetCaptionHeight(int nHeight)
+ // Sets the height of the caption
+ {
+ m_NCHeight = nHeight;
+ RedrawWindow();
+ RecalcDockLayout();
+ }
+
+ inline void CDocker::SetDockSize(int DockSize)
+ // Sets the size of a docked docker
+ {
+ if (IsDocked())
+ {
+ assert (m_pDockParent);
+ switch (GetDockStyle() & 0xF)
+ {
+ case DS_DOCKED_LEFT:
+ m_DockStartSize = MIN(DockSize,m_pDockParent->GetWindowRect().Width());
+ m_DockSizeRatio = ((double)m_DockStartSize)/((double)m_pDockParent->GetWindowRect().Width());
+ break;
+ case DS_DOCKED_RIGHT:
+ m_DockStartSize = MIN(DockSize,m_pDockParent->GetWindowRect().Width());
+ m_DockSizeRatio = ((double)m_DockStartSize)/((double)m_pDockParent->GetWindowRect().Width());
+ break;
+ case DS_DOCKED_TOP:
+ m_DockStartSize = MIN(DockSize,m_pDockParent->GetWindowRect().Height());
+ m_DockSizeRatio = ((double)m_DockStartSize)/((double)m_pDockParent->GetWindowRect().Height());
+ break;
+ case DS_DOCKED_BOTTOM:
+ m_DockStartSize = MIN(DockSize,m_pDockParent->GetWindowRect().Height());
+ m_DockSizeRatio = ((double)m_DockStartSize)/((double)m_pDockParent->GetWindowRect().Height());
+ break;
+ }
+
+ RecalcDockLayout();
+ }
+ else
+ {
+ m_DockStartSize = DockSize;
+ m_DockSizeRatio = 1.0;
+ }
+ }
+
+ inline void CDocker::SetDragAutoResize(BOOL bAutoResize)
+ {
+ m_bDragAutoResize = bAutoResize;
+ }
+
+ inline void CDocker::SetView(CWnd& wndView)
+ // Assigns the view window to the docker
+ {
+ CWnd* pWnd = &wndView;
+ GetDockClient().SetView(wndView);
+ if (dynamic_cast<CDockContainer*>(pWnd))
+ {
+ CDockContainer* pContainer = (CDockContainer*)&wndView;
+ SetCaption(pContainer->GetDockCaption().c_str());
+ }
+ }
+
+ inline void CDocker::PromoteFirstChild()
+ // One of the steps required for undocking
+ {
+ // Promote our first child to replace ourself
+ if (m_pDockParent)
+ {
+ for (UINT u = 0 ; u < m_pDockParent->m_vDockChildren.size(); ++u)
+ {
+ if (m_pDockParent->m_vDockChildren[u] == this)
+ {
+ if (m_vDockChildren.size() > 0)
+ // swap our first child for ourself as a child of the parent
+ m_pDockParent->m_vDockChildren[u] = m_vDockChildren[0];
+ else
+ // remove ourself as a child of the parent
+ m_pDockParent->m_vDockChildren.erase(m_pDockParent->m_vDockChildren.begin() + u);
+ break;
+ }
+ }
+ }
+
+ // Transfer styles and data and children to the child docker
+ CDocker* pDockFirstChild = NULL;
+ if (m_vDockChildren.size() > 0)
+ {
+ pDockFirstChild = m_vDockChildren[0];
+ pDockFirstChild->m_DockStyle = (pDockFirstChild->m_DockStyle & 0xFFFFFFF0 ) | (m_DockStyle & 0xF);
+ pDockFirstChild->m_DockStartSize = m_DockStartSize;
+ pDockFirstChild->m_DockSizeRatio = m_DockSizeRatio;
+
+ if (m_pDockParent)
+ {
+ pDockFirstChild->m_pDockParent = m_pDockParent;
+ pDockFirstChild->SetParent(m_pDockParent);
+ pDockFirstChild->GetDockBar().SetParent(m_pDockParent);
+ }
+ else
+ {
+ std::vector<CDocker*>::iterator iter;
+ for (iter = GetDockChildren().begin() + 1; iter < GetDockChildren().end(); ++iter)
+ (*iter)->ShowWindow(SW_HIDE);
+
+ pDockFirstChild->ConvertToPopup(GetWindowRect());
+ pDockFirstChild->GetDockBar().ShowWindow(SW_HIDE);
+ }
+
+ m_vDockChildren.erase(m_vDockChildren.begin());
+ MoveDockChildren(pDockFirstChild);
+ }
+ }
+
+ inline void CDocker::ConvertToChild(HWND hWndParent)
+ {
+ DWORD dwStyle = WS_CHILD | WS_VISIBLE;
+ SetWindowLongPtr(GWL_STYLE, dwStyle);
+ SetParent(FromHandle(hWndParent));
+ GetDockBar().SetParent(FromHandle(hWndParent));
+ }
+
+ inline void CDocker::ConvertToPopup(RECT rc)
+ {
+ // Change the window to an "undocked" style
+ ShowWindow(SW_HIDE);
+ DWORD dwStyle = WS_POPUP| WS_CAPTION | WS_SYSMENU | WS_THICKFRAME;
+ SetWindowLongPtr(GWL_STYLE, dwStyle);
+
+ // Change the window's parent and reposition it
+ GetDockBar().ShowWindow(SW_HIDE);
+ SetWindowPos(0, 0, 0, 0, 0, SWP_NOSENDCHANGING|SWP_HIDEWINDOW|SWP_NOREDRAW);
+ m_pDockParent = 0;
+ SetParent(0);
+ SetWindowPos(NULL, rc, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOOWNERZORDER);
+ GetDockClient().SetWindowPos(NULL, GetClientRect(), SWP_SHOWWINDOW);
+
+ SetWindowText(GetCaption().c_str());
+ }
+
+ inline CDocker* CDocker::SeparateFromDock()
+ {
+ // This performs some of the tasks required for undocking.
+ // It is also used when a docker is hidden.
+ CDocker* pDockUndockedFrom = GetDockParent();
+ if (!pDockUndockedFrom && (GetDockChildren().size() > 0))
+ pDockUndockedFrom = GetDockChildren()[0];
+
+ GetTopmostDocker()->m_hOldFocus = 0;
+ PromoteFirstChild();
+ m_pDockParent = 0;
+
+ GetDockBar().ShowWindow(SW_HIDE);
+ m_DockStyle = m_DockStyle & 0xFFFFFFF0;
+ m_DockStyle &= ~DS_DOCKED_CONTAINER;
+
+ return pDockUndockedFrom;
+ }
+
+ inline void CDocker::SetUndockPosition(CPoint pt)
+ {
+ m_Undocking = TRUE;
+ CRect rc;
+ rc = GetDockClient().GetWindowRect();
+ CRect rcTest = rc;
+ rcTest.bottom = MIN(rcTest.bottom, rcTest.top + m_NCHeight);
+ if ( !rcTest.PtInRect(pt))
+ rc.SetRect(pt.x - rc.Width()/2, pt.y - m_NCHeight/2, pt.x + rc.Width()/2, pt.y - m_NCHeight/2 + rc.Height());
+
+ ConvertToPopup(rc);
+ m_Undocking = FALSE;
+
+ // Send the undock notification to the frame
+ NMHDR nmhdr = {0};
+ nmhdr.hwndFrom = m_hWnd;
+ nmhdr.code = UWM_UNDOCKED;
+ nmhdr.idFrom = m_nDockID;
+ CWnd* pFrame = GetDockAncestor()->GetAncestor();
+ pFrame->SendMessage(WM_NOTIFY, m_nDockID, (LPARAM)&nmhdr);
+
+ // Initiate the window move
+ SetCursorPos(pt.x, pt.y);
+ ScreenToClient(pt);
+ PostMessage(WM_SYSCOMMAND, (WPARAM)(SC_MOVE|0x0002), MAKELPARAM(pt.x, pt.y));
+ }
+
+ inline void CDocker::Undock(CPoint pt, BOOL bShowUndocked)
+ {
+ // Return if we shouldn't undock
+ if (GetDockStyle() & DS_NO_UNDOCK) return;
+
+ // Undocking isn't supported on Win95
+ if (1400 == GetWinVersion()) return;
+
+ CDocker* pDockUndockedFrom = SeparateFromDock();
+
+ // Position and draw the undocked window, unless it is about to be closed
+ if (bShowUndocked)
+ {
+ SetUndockPosition(pt);
+ }
+
+ RecalcDockLayout();
+ if ((pDockUndockedFrom) && (pDockUndockedFrom->GetTopmostDocker() != GetTopmostDocker()))
+ pDockUndockedFrom->RecalcDockLayout();
+ }
+
+ inline void CDocker::UndockContainer(CDockContainer* pContainer, CPoint pt, BOOL bShowUndocked)
+ {
+ assert(pContainer);
+ assert(this == GetDockFromView(pContainer->GetContainerParent()));
+
+ // Return if we shouldn't undock
+ if (GetDockFromView(pContainer)->GetDockStyle() & DS_NO_UNDOCK) return;
+
+ // Undocking isn't supported on Win95
+ if (1400 == GetWinVersion()) return;
+
+ GetTopmostDocker()->m_hOldFocus = 0;
+ CDocker* pDockUndockedFrom = GetDockFromView(pContainer->GetContainerParent());
+ pDockUndockedFrom->ShowWindow(SW_HIDE);
+ if (GetView() == pContainer)
+ {
+ // The parent container is being undocked, so we need
+ // to transfer our child containers to a different docker
+
+ // Choose a new docker from among the dockers for child containers
+ CDocker* pDockNew = 0;
+ CDocker* pDockOld = GetDockFromView(pContainer);
+ std::vector<ContainerInfo> AllContainers = pContainer->GetAllContainers();
+ std::vector<ContainerInfo>::iterator iter = AllContainers.begin();
+ while ((0 == pDockNew) && (iter < AllContainers.end()))
+ {
+ if ((*iter).pContainer != pContainer)
+ pDockNew = (CDocker*)FromHandle(::GetParent((*iter).pContainer->GetParent()->GetHwnd()));
+
+ ++iter;
+ }
+
+ if (pDockNew)
+ {
+ // Move containers from the old docker to the new docker
+ CDockContainer* pContainerNew = (CDockContainer*)pDockNew->GetView();
+ for (iter = AllContainers.begin(); iter != AllContainers.end(); ++iter)
+ {
+ if ((*iter).pContainer != pContainer)
+ {
+ CDockContainer* pChildContainer = (CDockContainer*)(*iter).pContainer;
+ pContainer->RemoveContainer(pChildContainer);
+ if (pContainerNew != pChildContainer)
+ {
+ pContainerNew->AddContainer(pChildContainer);
+ CDocker* pDock = GetDockFromView(pChildContainer);
+ pDock->SetParent(pDockNew);
+ pDock->m_pDockParent = pDockNew;
+ }
+ }
+ }
+
+ // Now transfer the old docker's settings to the new one.
+ pDockUndockedFrom = pDockNew;
+ pDockNew->m_DockStyle = pDockOld->m_DockStyle;
+ pDockNew->m_DockStartSize = pDockOld->m_DockStartSize;
+ pDockNew->m_DockSizeRatio = pDockOld->m_DockSizeRatio;
+ if (pDockOld->IsDocked())
+ {
+ pDockNew->m_pDockParent = pDockOld->m_pDockParent;
+ pDockNew->SetParent(pDockOld->GetParent());
+ }
+ else
+ {
+ CRect rc = pDockOld->GetWindowRect();
+ pDockNew->ShowWindow(SW_HIDE);
+ DWORD dwStyle = WS_POPUP| WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_VISIBLE;
+ pDockNew->SetWindowLongPtr(GWL_STYLE, dwStyle);
+ pDockNew->m_pDockParent = 0;
+ pDockNew->SetParent(0);
+ pDockNew->SetWindowPos(NULL, rc, SWP_SHOWWINDOW|SWP_FRAMECHANGED| SWP_NOOWNERZORDER);
+ }
+ pDockNew->GetDockBar().SetParent(pDockOld->GetParent());
+ pDockNew->GetView()->SetFocus();
+
+ // Transfer the Dock children to the new docker
+ pDockOld->MoveDockChildren(pDockNew);
+
+ // insert pDockNew into its DockParent's DockChildren vector
+ if (pDockNew->m_pDockParent)
+ {
+ std::vector<CDocker*>::iterator p;
+ for (p = pDockNew->m_pDockParent->m_vDockChildren.begin(); p != pDockNew->m_pDockParent->m_vDockChildren.end(); ++p)
+ {
+ if (*p == this)
+ {
+ pDockNew->m_pDockParent->m_vDockChildren.insert(p, pDockNew);
+ break;
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ // This is a child container, so simply remove it from the parent
+ CDockContainer* pContainerParent = (CDockContainer*)GetView();
+ pContainerParent->RemoveContainer(pContainer);
+ pContainerParent->SetTabSize();
+ pContainerParent->SetFocus();
+ pContainerParent->GetViewPage().SetParent(pContainerParent);
+ }
+
+ // Finally do the actual undocking
+ CDocker* pDock = GetDockFromView(pContainer);
+ CRect rc = GetDockClient().GetWindowRect();
+ ScreenToClient(rc);
+ pDock->GetDockClient().SetWindowPos(NULL, rc, SWP_SHOWWINDOW);
+ pDock->Undock(pt, bShowUndocked);
+ pDockUndockedFrom->ShowWindow();
+ pDockUndockedFrom->RecalcDockLayout();
+ pDock->BringWindowToTop();
+ }
+
+ inline LRESULT CDocker::WndProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam)
+ {
+ switch (uMsg)
+ {
+ case WM_ACTIVATE:
+ OnActivate(wParam, lParam);
+ break;
+ case WM_SYSCOMMAND:
+ return OnSysCommand(wParam, lParam);
+
+ case WM_EXITSIZEMOVE:
+ OnExitSizeMove(wParam, lParam);
+ break;
+ case WM_WINDOWPOSCHANGING:
+ return OnWindowPosChanging(wParam, lParam);
+
+ case WM_WINDOWPOSCHANGED:
+ OnWindowPosChanged(wParam, lParam);
+ break;
+ case WM_DESTROY:
+ OnDestroy(wParam, lParam);
+ break;
+ case WM_SETFOCUS:
+ OnSetFocus(wParam, lParam);
+ break;
+ case WM_TIMER:
+ OnCaptionTimer(wParam, lParam);
+ break;
+ case UWM_DOCK_DESTROYED:
+ OnDockDestroyed(wParam, lParam);
+ break;
+ case UWM_DOCK_ACTIVATED:
+ DrawAllCaptions();
+ SetTimer(1, 100, NULL);
+ break;
+ case WM_SYSCOLORCHANGE:
+ OnSysColorChange(wParam, lParam);
+ break;
+ case WM_NCLBUTTONDBLCLK :
+ m_bIsDragging = FALSE;
+ break;
+ }
+
+ return CWnd::WndProcDefault(uMsg, wParam, lParam);
+ }
+
+
+ //////////////////////////////////////
+ // Declaration of the CDockContainer class
+ inline CDockContainer::CDockContainer() : m_iCurrentPage(0), m_hTabIcon(0), m_nTabPressed(-1)
+ {
+ m_pContainerParent = this;
+ }
+
+ inline CDockContainer::~CDockContainer()
+ {
+ if (m_hTabIcon)
+ DestroyIcon(m_hTabIcon);
+ }
+
+ inline void CDockContainer::AddContainer(CDockContainer* pContainer)
+ {
+ assert(pContainer);
+
+ if (this == m_pContainerParent)
+ {
+ ContainerInfo ci = {0};
+ ci.pContainer = pContainer;
+ lstrcpy(ci.szTitle, pContainer->GetTabText());
+ ci.iImage = ImageList_AddIcon(GetImageList(), pContainer->GetTabIcon());
+ int iNewPage = (int)m_vContainerInfo.size();
+ m_vContainerInfo.push_back(ci);
+
+ if (m_hWnd)
+ {
+ TCITEM tie = {0};
+ tie.mask = TCIF_TEXT | TCIF_IMAGE;
+ tie.iImage = ci.iImage;
+ tie.pszText = m_vContainerInfo[iNewPage].szTitle;
+ TabCtrl_InsertItem(m_hWnd, iNewPage, &tie);
+
+ SetTabSize();
+ }
+
+ pContainer->m_pContainerParent = this;
+ if (pContainer->IsWindow())
+ {
+ // Set the parent container relationships
+ pContainer->GetViewPage().SetParent(this);
+ pContainer->GetViewPage().ShowWindow(SW_HIDE);
+ }
+ }
+ }
+
+ inline void CDockContainer::AddToolBarButton(UINT nID, BOOL bEnabled /* = TRUE */)
+ // Adds Resource IDs to toolbar buttons.
+ // A resource ID of 0 is a separator
+ {
+ GetToolBar().AddButton(nID, bEnabled);
+ }
+
+ inline CDockContainer* CDockContainer::GetContainerFromIndex(UINT nPage)
+ {
+ CDockContainer* pContainer = NULL;
+ if (nPage < m_vContainerInfo.size())
+ pContainer = (CDockContainer*)m_vContainerInfo[nPage].pContainer;
+
+ return pContainer;
+ }
+
+ inline CWnd* CDockContainer::GetActiveView() const
+ // Returns a pointer to the active view window, or NULL if there is no active veiw.
+ {
+ CWnd* pWnd = NULL;
+ if (m_pContainerParent->m_vContainerInfo.size() > 0)
+ {
+ CDockContainer* pActiveContainer = m_pContainerParent->m_vContainerInfo[m_pContainerParent->m_iCurrentPage].pContainer;
+ if (pActiveContainer->GetViewPage().GetView()->IsWindow())
+ pWnd = pActiveContainer->GetViewPage().GetView();
+ }
+
+ return pWnd;
+ }
+
+ inline CDockContainer* CDockContainer::GetContainerFromView(CWnd* pView) const
+ {
+ assert(pView);
+
+ std::vector<ContainerInfo>::iterator iter;
+ CDockContainer* pViewContainer = 0;
+ for (iter = GetAllContainers().begin(); iter != GetAllContainers().end(); ++iter)
+ {
+ CDockContainer* pContainer = (*iter).pContainer;
+ if (pContainer->GetView() == pView)
+ pViewContainer = pContainer;
+ }
+
+ return pViewContainer;
+ }
+
+ inline int CDockContainer::GetContainerIndex(CDockContainer* pContainer)
+ {
+ assert(pContainer);
+ int iReturn = -1;
+
+ for (int i = 0; i < (int)m_pContainerParent->m_vContainerInfo.size(); ++i)
+ {
+ if (m_pContainerParent->m_vContainerInfo[i].pContainer == pContainer)
+ iReturn = i;
+ }
+
+ return iReturn;
+ }
+
+ inline SIZE CDockContainer::GetMaxTabTextSize()
+ {
+ CSize Size;
+
+ // Allocate an iterator for the ContainerInfo vector
+ std::vector<ContainerInfo>::iterator iter;
+
+ for (iter = m_vContainerInfo.begin(); iter != m_vContainerInfo.end(); ++iter)
+ {
+ CSize TempSize;
+ CClientDC dc(this);
+ NONCLIENTMETRICS info = {0};
+ info.cbSize = GetSizeofNonClientMetrics();
+ SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(info), &info, 0);
+ dc.CreateFontIndirect(&info.lfStatusFont);
+ TempSize = dc.GetTextExtentPoint32(iter->szTitle, lstrlen(iter->szTitle));
+ if (TempSize.cx > Size.cx)
+ Size = TempSize;
+ }
+
+ return Size;
+ }
+
+ inline void CDockContainer::SetupToolBar()
+ {
+ // Use this function to set the Resource IDs for the toolbar(s).
+
+/* // Set the Resource IDs for the toolbar buttons
+ AddToolBarButton( IDM_FILE_NEW );
+ AddToolBarButton( IDM_FILE_OPEN );
+ AddToolBarButton( IDM_FILE_SAVE );
+ AddToolBarButton( 0 ); // Separator
+ AddToolBarButton( IDM_EDIT_CUT );
+ AddToolBarButton( IDM_EDIT_COPY );
+ AddToolBarButton( IDM_EDIT_PASTE );
+ AddToolBarButton( 0 ); // Separator
+ AddToolBarButton( IDM_FILE_PRINT );
+ AddToolBarButton( 0 ); // Separator
+ AddToolBarButton( IDM_HELP_ABOUT );
+*/
+ }
+
+ inline void CDockContainer::OnCreate()
+ {
+ assert(GetView()); // Use SetView in CMainFrame's constructor to set the view window
+
+ ContainerInfo ci = {0};
+ ci.pContainer = this;
+ lstrcpy(ci.szTitle, GetTabText());
+ ci.iImage = ImageList_AddIcon(GetImageList(), GetTabIcon());
+ m_vContainerInfo.push_back(ci);
+
+ // Create the page window
+ GetViewPage().Create(this);
+
+ // Create the toolbar
+ GetToolBar().Create(&GetViewPage());
+ DWORD style = (DWORD)GetToolBar().GetWindowLongPtr(GWL_STYLE);
+ style |= CCS_NODIVIDER ;
+ GetToolBar().SetWindowLongPtr(GWL_STYLE, style);
+ SetupToolBar();
+ if (GetToolBar().GetToolBarData().size() > 0)
+ {
+ // Set the toolbar images
+ // A mask of 192,192,192 is compatible with AddBitmap (for Win95)
+ if (!GetToolBar().SendMessage(TB_GETIMAGELIST, 0L, 0L))
+ GetToolBar().SetImages(RGB(192,192,192), IDW_MAIN, 0, 0);
+
+ GetToolBar().SendMessage(TB_AUTOSIZE, 0L, 0L);
+ }
+ else
+ GetToolBar().Destroy();
+
+ SetFixedWidth(TRUE);
+ SetOwnerDraw(TRUE);
+
+ // Add tabs for each container.
+ for (int i = 0; i < (int)m_vContainerInfo.size(); ++i)
+ {
+ // Add tabs for each view.
+ TCITEM tie = {0};
+ tie.mask = TCIF_TEXT | TCIF_IMAGE;
+ tie.iImage = i;
+ tie.pszText = m_vContainerInfo[i].szTitle;
+ TabCtrl_InsertItem(m_hWnd, i, &tie);
+ }
+ }
+
+ inline void CDockContainer::OnLButtonDown(WPARAM wParam, LPARAM lParam)
+ {
+ // Overrides CTab::OnLButtonDown
+
+ UNREFERENCED_PARAMETER(wParam);
+
+ CPoint pt((DWORD)lParam);
+ TCHITTESTINFO info = {0};
+ info.pt = pt;
+ m_nTabPressed = HitTest(info);
+ }
+
+ inline void CDockContainer::OnLButtonUp(WPARAM wParam, LPARAM lParam)
+ {
+ // Overrides CTab::OnLButtonUp and takes no action
+
+ UNREFERENCED_PARAMETER(wParam);
+ UNREFERENCED_PARAMETER(lParam);
+ }
+
+ inline void CDockContainer::OnMouseLeave(WPARAM wParam, LPARAM lParam)
+ {
+ // Overrides CTab::OnMouseLeave
+
+ if (IsLeftButtonDown() && (m_nTabPressed >= 0))
+ {
+ CDocker* pDock = (CDocker*)FromHandle(::GetParent(GetParent()->GetHwnd()));
+ if (dynamic_cast<CDocker*>(pDock))
+ {
+ CDockContainer* pContainer = GetContainerFromIndex(m_iCurrentPage);
+ pDock->UndockContainer(pContainer, GetCursorPos(), TRUE);
+ }
+ }
+
+ m_nTabPressed = -1;
+ CTab::OnMouseLeave(wParam, lParam);
+ }
+
+ inline LRESULT CDockContainer::OnNotifyReflect(WPARAM wParam, LPARAM lParam)
+ {
+ UNREFERENCED_PARAMETER(wParam);
+
+ switch (((LPNMHDR)lParam)->code)
+ {
+ case TCN_SELCHANGE:
+ {
+ // Display the newly selected tab page
+ int nPage = GetCurSel();
+ SelectPage(nPage);
+ }
+ break;
+ }
+
+ return 0L;
+ }
+
+ inline void CDockContainer::PreCreate(CREATESTRUCT &cs)
+ {
+ // For Tabs on the bottom, add the TCS_BOTTOM style
+ CTab::PreCreate(cs);
+ cs.style |= TCS_BOTTOM;
+ }
+
+ inline void CDockContainer::RecalcLayout()
+ {
+ if (GetContainerParent() == this)
+ {
+ // Set the tab sizes
+ SetTabSize();
+
+ // Position the View over the tab control's display area
+ CRect rc = GetClientRect();
+ AdjustRect(FALSE, &rc);
+ CDockContainer* pContainer = m_vContainerInfo[m_iCurrentPage].pContainer;
+ pContainer->GetViewPage().SetWindowPos(HWND_TOP, rc, SWP_SHOWWINDOW);
+ }
+ }
+
+ inline void CDockContainer::RemoveContainer(CDockContainer* pWnd)
+ {
+ assert(pWnd);
+
+ // Remove the tab
+ int iTab = GetContainerIndex(pWnd);
+ if (iTab > 0)
+ {
+ // DeleteItem(iTab);
+ TabCtrl_DeleteItem(m_hWnd, iTab);
+ }
+
+ // Remove the ContainerInfo entry
+ std::vector<ContainerInfo>::iterator iter;
+ int iImage = -1;
+ for (iter = m_vContainerInfo.begin(); iter != m_vContainerInfo.end(); ++iter)
+ {
+ if (iter->pContainer == pWnd)
+ {
+ iImage = (*iter).iImage;
+ if (iImage >= 0)
+ TabCtrl_RemoveImage(m_hWnd, iImage);
+
+ m_vContainerInfo.erase(iter);
+ break;
+ }
+ }
+
+ // Set the parent container relationships
+ pWnd->GetViewPage().SetParent(pWnd);
+ pWnd->m_pContainerParent = pWnd;
+
+ // Display the first page
+ m_iCurrentPage = 0;
+ if (IsWindow())
+ SelectPage(0);
+ }
+
+ inline void CDockContainer::SelectPage(int nPage)
+ {
+ if (this != m_pContainerParent)
+ m_pContainerParent->SelectPage(nPage);
+ else
+ {
+ if ((nPage >= 0) && (nPage < (int)m_vContainerInfo.size() ))
+ {
+ if (GetCurSel() != nPage)
+ SetCurSel(nPage);
+
+ // Create the new container window if required
+ if (!m_vContainerInfo[nPage].pContainer->IsWindow())
+ {
+ CDockContainer* pContainer = m_vContainerInfo[nPage].pContainer;
+ pContainer->Create(GetParent());
+ pContainer->GetViewPage().SetParent(this);
+ }
+
+ // Determine the size of the tab page's view area
+ CRect rc = GetClientRect();
+ AdjustRect(FALSE, &rc);
+
+ // Swap the pages over
+ CDockContainer* pOldContainer = m_vContainerInfo[m_iCurrentPage].pContainer;
+ CDockContainer* pNewContainer = m_vContainerInfo[nPage].pContainer;
+ pOldContainer->GetViewPage().ShowWindow(SW_HIDE);
+ pNewContainer->GetViewPage().SetWindowPos(HWND_TOP, rc, SWP_SHOWWINDOW);
+ pNewContainer->GetViewPage().GetView()->SetFocus();
+
+ // Adjust the docking caption
+ CDocker* pDock = (CDocker*)FromHandle(::GetParent(::GetParent(m_hWnd)));
+ if (dynamic_cast<CDocker*>(pDock))
+ {
+ pDock->SetCaption(pNewContainer->GetDockCaption().c_str());
+ pDock->RedrawWindow();
+ }
+
+ m_iCurrentPage = nPage;
+ }
+ }
+ }
+
+ inline void CDockContainer::SetActiveContainer(CDockContainer* pContainer)
+ {
+ int nPage = GetContainerIndex(pContainer);
+ assert (0 <= nPage);
+ SelectPage(nPage);
+ }
+
+ inline void CDockContainer::SetTabIcon(UINT nID_Icon)
+ {
+ HICON hIcon = (HICON)LoadImage(GetApp()->GetResourceHandle(), MAKEINTRESOURCE(nID_Icon), IMAGE_ICON, 0, 0, LR_SHARED);
+ SetTabIcon(hIcon);
+ }
+
+ inline void CDockContainer::SetTabSize()
+ {
+ CRect rc = GetClientRect();
+ AdjustRect(FALSE, &rc);
+ if (rc.Width() < 0 )
+ rc.SetRectEmpty();
+
+ int nItemWidth = MIN(25 + GetMaxTabTextSize().cx, (rc.Width()-2)/(int)m_vContainerInfo.size());
+ int nItemHeight = MAX(20, GetTextHeight() + 5);
+ SendMessage(TCM_SETITEMSIZE, 0L, MAKELPARAM(nItemWidth, nItemHeight));
+ }
+
+ inline void CDockContainer::SetTabText(UINT nTab, LPCTSTR szText)
+ {
+ CDockContainer* pContainer = GetContainerParent()->GetContainerFromIndex(nTab);
+ pContainer->SetTabText(szText);
+
+ CTab::SetTabText(nTab, szText);
+ }
+
+ inline void CDockContainer::SetView(CWnd& Wnd)
+ {
+ GetViewPage().SetView(Wnd);
+ }
+
+ inline LRESULT CDockContainer::WndProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam)
+ {
+ switch (uMsg)
+ {
+ case WM_SIZE:
+ RecalcLayout();
+ return 0;
+
+ // The following are called in CTab::WndProcDefault
+ // case WM_LBUTTONDOWN:
+ // OnLButtonDown(wParam, lParam);
+ // break;
+ // case WM_LBUTTONUP:
+ // OnLButtonUp(wParam, lParam);
+ // break;
+ // case WM_MOUSELEAVE:
+ // OnMouseLeave(wParam, lParam);
+ // break;
+
+ case WM_SETFOCUS:
+ {
+ // Pass focus on to the current view
+ GetActiveView()->SetFocus();
+ }
+ break;
+ }
+
+ // pass unhandled messages on to CTab for processing
+ return CTab::WndProcDefault(uMsg, wParam, lParam);
+ }
+
+
+ ///////////////////////////////////////////
+ // Declaration of the nested CViewPage class
+ inline BOOL CDockContainer::CViewPage::OnCommand(WPARAM wParam, LPARAM lParam)
+ {
+ CDockContainer* pContainer = (CDockContainer*)GetParent();
+ BOOL bResult = FALSE;
+ if (pContainer && pContainer->GetActiveContainer())
+ bResult = (BOOL)pContainer->GetActiveContainer()->SendMessage(WM_COMMAND, wParam, lParam);
+
+ return bResult;
+ }
+
+ inline void CDockContainer::CViewPage::OnCreate()
+ {
+ if (m_pView)
+ m_pView->Create(this);
+ }
+
+ inline LRESULT CDockContainer::CViewPage::OnNotify(WPARAM wParam, LPARAM lParam)
+ {
+ UNREFERENCED_PARAMETER(wParam);
+
+ switch (((LPNMHDR)lParam)->code)
+ {
+
+ // Display tooltips for the toolbar
+ case TTN_GETDISPINFO:
+ {
+ int iIndex = GetToolBar().HitTest();
+ LPNMTTDISPINFO lpDispInfo = (LPNMTTDISPINFO)lParam;
+ if (iIndex >= 0)
+ {
+ int nID = GetToolBar().GetCommandID(iIndex);
+ if (nID > 0)
+ {
+ m_tsTooltip = LoadString(nID);
+ lpDispInfo->lpszText = (LPTSTR)m_tsTooltip.c_str();
+ }
+ else
+ m_tsTooltip = _T("");
+ }
+ }
+ break;
+ } // switch LPNMHDR
+
+ return 0L;
+ }
+
+ inline void CDockContainer::CViewPage::PreRegisterClass(WNDCLASS &wc)
+ {
+ wc.lpszClassName = _T("Win32++ TabPage");
+ wc.hCursor = ::LoadCursor(NULL, IDC_ARROW);
+ }
+
+ inline void CDockContainer::CViewPage::RecalcLayout()
+ {
+ CRect rc = GetClientRect();
+ if (GetToolBar().IsWindow())
+ {
+ GetToolBar().SendMessage(TB_AUTOSIZE, 0L, 0L);
+ CRect rcToolBar = m_ToolBar.GetClientRect();
+ rc.top += rcToolBar.Height();
+ }
+
+ GetView()->SetWindowPos(NULL, rc, SWP_SHOWWINDOW);
+ }
+
+ inline void CDockContainer::CViewPage::SetView(CWnd& wndView)
+ // Sets or changes the View window displayed within the frame
+ {
+ // Assign the view window
+ m_pView = &wndView;
+
+ if (m_hWnd)
+ {
+ if (!m_pView->IsWindow())
+ {
+ // The container is already created, so create and position the new view too
+ GetView()->Create(this);
+ }
+
+ RecalcLayout();
+ }
+ }
+
+ inline LRESULT CDockContainer::CViewPage::WndProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam)
+ {
+ switch (uMsg)
+ {
+ case WM_SIZE:
+ RecalcLayout();
+ break;
+ case WM_NOTIFY:
+ switch (((LPNMHDR)lParam)->code)
+ {
+ // Send the focus change notifications to the grandparent
+ case NM_KILLFOCUS:
+ case NM_SETFOCUS:
+ case UWM_FRAMELOSTFOCUS:
+ ::SendMessage(::GetParent(::GetParent(m_hWnd)), WM_NOTIFY, wParam, lParam);
+ break;
+ }
+
+ break;
+ }
+
+ // pass unhandled messages on for default processing
+ return CWnd::WndProcDefault(uMsg, wParam, lParam);
+ }
+
+} // namespace Win32xx
+
+#endif // _WIN32XX_DOCKING_H_
+
diff --git a/mmc_updater/depends/win32cpp/file.h b/mmc_updater/depends/win32cpp/file.h
new file mode 100644
index 00000000..4316dc94
--- /dev/null
+++ b/mmc_updater/depends/win32cpp/file.h
@@ -0,0 +1,392 @@
+// Win32++ Version 7.2
+// Released: 5th AUgust 2011
+//
+// David Nash
+// email: dnash@bigpond.net.au
+// url: https://sourceforge.net/projects/win32-framework
+//
+//
+// Copyright (c) 2005-2011 David Nash
+//
+// Permission is hereby granted, free of charge, to
+// any person obtaining a copy of this software and
+// associated documentation files (the "Software"),
+// to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify,
+// merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom
+// the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice
+// shall be included in all copies or substantial portions
+// of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
+// OR OTHER DEALINGS IN THE SOFTWARE.
+//
+////////////////////////////////////////////////////////
+
+
+#ifndef _WIN32XX_FILE_H_
+#define _WIN32XX_FILE_H_
+
+
+#include "wincore.h"
+
+namespace Win32xx
+{
+
+ class CFile
+ {
+ public:
+ CFile();
+ CFile(HANDLE hFile);
+ CFile(LPCTSTR pszFileName, UINT nOpenFlags);
+ ~CFile();
+ operator HANDLE() const;
+
+ BOOL Close();
+ BOOL Flush();
+ HANDLE GetHandle() const;
+ ULONGLONG GetLength() const;
+ const CString& GetFileName() const;
+ const CString& GetFilePath() const;
+ const CString& GetFileTitle() const;
+ ULONGLONG GetPosition() const;
+ BOOL LockRange(ULONGLONG Pos, ULONGLONG Count);
+ BOOL Open(LPCTSTR pszFileName, UINT nOpenFlags);
+ CString OpenFileDialog(LPCTSTR pszFilePathName = NULL,
+ DWORD dwFlags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, LPCTSTR pszFilter = NULL,
+ CWnd* pOwnerWnd = NULL);
+ UINT Read(void* pBuf, UINT nCount);
+ static BOOL Remove(LPCTSTR pszFileName);
+ static BOOL Rename(LPCTSTR pszOldName, LPCTSTR pszNewName);
+ CString SaveFileDialog(LPCTSTR pszFilePathName = NULL,
+ DWORD dwFlags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, LPCTSTR pszFilter = NULL,
+ LPCTSTR pszDefExt = NULL, CWnd* pOwnerWnd = NULL);
+ ULONGLONG Seek(LONGLONG lOff, UINT nFrom);
+ void SeekToBegin();
+ ULONGLONG SeekToEnd();
+ void SetFilePath(LPCTSTR pszNewName);
+ BOOL SetLength(ULONGLONG NewLen);
+ BOOL UnlockRange(ULONGLONG Pos, ULONGLONG Count);
+ BOOL Write(const void* pBuf, UINT nCount);
+
+ private:
+ CFile(const CFile&); // Disable copy construction
+ CFile& operator = (const CFile&); // Disable assignment operator
+ CString m_FileName;
+ CString m_FilePath;
+ CString m_FileTitle;
+ HANDLE m_hFile;
+ };
+
+}
+
+
+
+namespace Win32xx
+{
+ inline CFile::CFile() : m_hFile(0)
+ {
+ }
+
+ inline CFile::CFile(HANDLE hFile) : m_hFile(hFile)
+ {
+ }
+
+ inline CFile::CFile(LPCTSTR pszFileName, UINT nOpenFlags) : m_hFile(0)
+ {
+ assert(pszFileName);
+ Open(pszFileName, nOpenFlags);
+ assert(m_hFile);
+ }
+
+ inline CFile::~CFile()
+ {
+ Close();
+ }
+
+ inline CFile::operator HANDLE() const
+ {
+ return m_hFile;
+ }
+
+ inline BOOL CFile::Close()
+ // Closes the file associated with this object. Closed file can no longer be read or written to.
+ {
+ BOOL bResult = TRUE;
+ if (m_hFile)
+ bResult = CloseHandle(m_hFile);
+
+ m_hFile = 0;
+ return bResult;
+ }
+
+ inline BOOL CFile::Flush()
+ // Causes any remaining data in the file buffer to be written to the file.
+ {
+ assert(m_hFile);
+ return FlushFileBuffers(m_hFile);
+ }
+
+ inline HANDLE CFile::GetHandle() const
+ {
+ return m_hFile;
+ }
+
+ inline ULONGLONG CFile::GetLength( ) const
+ // Returns the length of the file in bytes.
+ {
+ assert(m_hFile);
+
+ LONG High = 0;
+ DWORD LowPos = SetFilePointer(m_hFile, 0, &High, FILE_END);
+
+ ULONGLONG Result = ((ULONGLONG)High << 32) + LowPos;
+ return Result;
+ }
+
+ inline const CString& CFile::GetFileName() const
+ // Returns the filename of the file associated with this object.
+ {
+ return (const CString&)m_FileName;
+ }
+
+ inline const CString& CFile::GetFilePath() const
+ // Returns the full filename including the directory of the file associated with this object.
+ {
+ return (const CString&)m_FilePath;
+ }
+
+ inline const CString& CFile::GetFileTitle() const
+ // Returns the filename of the file associated with this object, excluding the path and the file extension
+ {
+ return (const CString&)m_FileTitle;
+ }
+
+ inline ULONGLONG CFile::GetPosition() const
+ // Returns the current value of the file pointer, which can be used in subsequent calls to Seek.
+ {
+ assert(m_hFile);
+ LONG High = 0;
+ DWORD LowPos = SetFilePointer(m_hFile, 0, &High, FILE_CURRENT);
+
+ ULONGLONG Result = ((ULONGLONG)High << 32) + LowPos;
+ return Result;
+ }
+
+ inline BOOL CFile::LockRange(ULONGLONG Pos, ULONGLONG Count)
+ // Locks a range of bytes in and open file.
+ {
+ assert(m_hFile);
+
+ DWORD dwPosHigh = (DWORD)(Pos >> 32);
+ DWORD dwPosLow = (DWORD)(Pos & 0xFFFFFFFF);
+ DWORD dwCountHigh = (DWORD)(Count >> 32);
+ DWORD dwCountLow = (DWORD)(Count & 0xFFFFFFFF);
+
+ return ::LockFile(m_hFile, dwPosLow, dwPosHigh, dwCountLow, dwCountHigh);
+ }
+
+ inline BOOL CFile::Open(LPCTSTR pszFileName, UINT nOpenFlags)
+ // Prepares a file to be written to or read from.
+ {
+ if (m_hFile) Close();
+
+ m_hFile = ::CreateFile(pszFileName, GENERIC_READ | GENERIC_WRITE, 0, NULL, nOpenFlags, FILE_ATTRIBUTE_NORMAL, NULL);
+
+ if (INVALID_HANDLE_VALUE == m_hFile)
+ {
+ TRACE(_T("Failed\n"));
+ m_hFile = 0;
+ }
+
+ if (m_hFile)
+ {
+ SetFilePath(pszFileName);
+ }
+
+ return (m_hFile != 0);
+ }
+
+ inline CString CFile::OpenFileDialog(LPCTSTR pszFilePathName, DWORD dwFlags, LPCTSTR pszFilter, CWnd* pOwnerWnd)
+ // Displays the file open dialog.
+ // Returns a CString containing either the selected file name or an empty CString.
+ {
+ CString str;
+ if (pszFilePathName)
+ str = pszFilePathName;
+
+ OPENFILENAME ofn = {0};
+ ofn.lStructSize = sizeof(OPENFILENAME);
+
+#if defined OPENFILENAME_SIZE_VERSION_400
+ if (GetWinVersion() < 2500)
+ ofn.lStructSize = OPENFILENAME_SIZE_VERSION_400;
+#endif
+
+ ofn.hwndOwner = pOwnerWnd? pOwnerWnd->GetHwnd() : NULL;
+ ofn.hInstance = GetApp()->GetInstanceHandle();
+ ofn.lpstrFilter = pszFilter;
+ ofn.lpstrTitle = _T("Open File");
+ ofn.Flags = dwFlags;
+ ofn.nMaxFile = _MAX_PATH;
+
+ ofn.lpstrFile = (LPTSTR)str.GetBuffer(_MAX_PATH);
+ ::GetOpenFileName(&ofn);
+ str.ReleaseBuffer();
+
+ return str;
+ }
+
+ inline UINT CFile::Read(void* pBuf, UINT nCount)
+ // Reads from the file, storing the contents in the specified buffer.
+ {
+ assert(m_hFile);
+ DWORD dwRead = 0;
+
+ if (!::ReadFile(m_hFile, pBuf, nCount, &dwRead, NULL))
+ dwRead = 0;
+
+ return dwRead;
+ }
+
+ inline BOOL CFile::Rename(LPCTSTR pszOldName, LPCTSTR pszNewName)
+ // Renames the specified file.
+ {
+ return ::MoveFile(pszOldName, pszNewName);
+ }
+
+ inline BOOL CFile::Remove(LPCTSTR pszFileName)
+ // Deletes the specified file.
+ {
+ return ::DeleteFile(pszFileName);
+ }
+
+ inline CString CFile::SaveFileDialog(LPCTSTR pszFilePathName, DWORD dwFlags, LPCTSTR pszFilter, LPCTSTR pszDefExt, CWnd* pOwnerWnd)
+ // Displays the SaveFileDialog.
+ // Returns a CString containing either the selected file name or an empty CString
+ {
+ CString str;
+ if (pszFilePathName)
+ str = pszFilePathName;
+
+ OPENFILENAME ofn = {0};
+ ofn.lStructSize = sizeof(OPENFILENAME);
+
+#if defined OPENFILENAME_SIZE_VERSION_400
+ if (GetWinVersion() < 2500)
+ ofn.lStructSize = OPENFILENAME_SIZE_VERSION_400;
+#endif
+
+ ofn.hwndOwner = pOwnerWnd? pOwnerWnd->GetHwnd() : NULL;
+ ofn.hInstance = GetApp()->GetInstanceHandle();
+ ofn.lpstrFilter = pszFilter;
+ ofn.lpstrFile = (LPTSTR)pszFilePathName;
+ ofn.lpstrFileTitle = (LPTSTR)pszFilePathName;
+ ofn.lpstrDefExt = pszDefExt;
+ ofn.nMaxFile = lstrlen(pszFilePathName);
+ ofn.lpstrTitle = _T("Save File");
+ ofn.Flags = dwFlags;
+ ofn.nMaxFile = _MAX_PATH;
+ ofn.lpstrFile = (LPTSTR)str.GetBuffer(_MAX_PATH);
+ ::GetSaveFileName(&ofn);
+ str.ReleaseBuffer();
+
+ return str;
+ }
+
+ inline ULONGLONG CFile::Seek(LONGLONG lOff, UINT nFrom)
+ // Positions the current file pointer.
+ // Permitted values for nFrom are: FILE_BEGIN, FILE_CURRENT, or FILE_END.
+ {
+ assert(m_hFile);
+ assert(nFrom == FILE_BEGIN || nFrom == FILE_CURRENT || nFrom == FILE_END);
+
+ LONG High = LONG(lOff >> 32);
+ LONG Low = (LONG)(lOff & 0xFFFFFFFF);
+
+ DWORD LowPos = SetFilePointer(m_hFile, Low, &High, nFrom);
+
+ ULONGLONG Result = ((ULONGLONG)High << 32) + LowPos;
+ return Result;
+ }
+
+ inline void CFile::SeekToBegin()
+ // Sets the current file pointer to the beginning of the file.
+ {
+ assert(m_hFile);
+ Seek(0, FILE_BEGIN);
+ }
+
+ inline ULONGLONG CFile::SeekToEnd()
+ // Sets the current file pointer to the end of the file.
+ {
+ assert(m_hFile);
+ return Seek(0, FILE_END);
+ }
+
+ inline void CFile::SetFilePath(LPCTSTR pszFileName)
+ // Specifies the full file name, including its path
+ {
+ TCHAR* pFileName = NULL;
+ int nBuffSize = ::GetFullPathName(pszFileName, 0, 0, 0);
+ if (nBuffSize > 0)
+ {
+ TCHAR* pBuff = m_FilePath.GetBuffer(nBuffSize);
+ ::GetFullPathName(pszFileName, nBuffSize, pBuff, &pFileName);
+ m_FilePath.ReleaseBuffer();
+ m_FileName = pFileName;
+ int nPos = m_FileName.ReverseFind(_T("."));
+ if (nPos >= 0)
+ m_FileTitle = m_FileName.Left(nPos);
+ }
+ }
+
+ inline BOOL CFile::SetLength(ULONGLONG NewLen)
+ // Changes the length of the file to the specified value.
+ {
+ assert(m_hFile);
+
+ Seek(NewLen, FILE_BEGIN);
+ return ::SetEndOfFile(m_hFile);
+ }
+
+ inline BOOL CFile::UnlockRange(ULONGLONG Pos, ULONGLONG Count)
+ // Unlocks a range of bytes in an open file.
+ {
+ assert(m_hFile);
+
+ DWORD dwPosHigh = (DWORD)(Pos >> 32);
+ DWORD dwPosLow = (DWORD)(Pos & 0xFFFFFFFF);
+ DWORD dwCountHigh = (DWORD)(Count >> 32);
+ DWORD dwCountLow = (DWORD)(Count & 0xFFFFFFFF);
+
+ return ::UnlockFile(m_hFile, dwPosLow, dwPosHigh, dwCountLow, dwCountHigh);
+ }
+
+ inline BOOL CFile::Write(const void* pBuf, UINT nCount)
+ // Writes the specified buffer to the file.
+ {
+ assert(m_hFile);
+ DWORD dwWritten = 0;
+ BOOL bResult = ::WriteFile(m_hFile, pBuf, nCount, &dwWritten, NULL);
+ if (dwWritten != nCount)
+ bResult = FALSE;
+
+ return bResult;
+ }
+
+
+} // namespace Win32xx
+
+#endif
diff --git a/mmc_updater/depends/win32cpp/frame.h b/mmc_updater/depends/win32cpp/frame.h
new file mode 100644
index 00000000..1f439fd7
--- /dev/null
+++ b/mmc_updater/depends/win32cpp/frame.h
@@ -0,0 +1,3303 @@
+// Win32++ Version 7.2
+// Released: 5th AUgust 2011
+//
+// David Nash
+// email: dnash@bigpond.net.au
+// url: https://sourceforge.net/projects/win32-framework
+//
+//
+// Copyright (c) 2005-2011 David Nash
+//
+// Permission is hereby granted, free of charge, to
+// any person obtaining a copy of this software and
+// associated documentation files (the "Software"),
+// to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify,
+// merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom
+// the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice
+// shall be included in all copies or substantial portions
+// of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
+// OR OTHER DEALINGS IN THE SOFTWARE.
+//
+////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////
+// frame.h
+// Declaration of the CFrame and CMenuBar classes
+
+// The classes declared in this file support SDI (Single Document Interface)
+// frames on Win32/Win64 operating systems (not Windows CE). For Windows CE,
+// use wceframe.h instead. SDI frames are a simple frame which supports a
+// single view window. Refer to mdi.h for frames that support several
+// child windows.
+
+// CFrame also includes each of the following classes as members:
+// * CReBar for managing the frame's rebar control.
+// * CMenuBar for managing the menu inside the rebar.
+// * CToolBar for managing the frame's toolbar.
+// * CStatusBar for managing the frame's status bar.
+// In each case these members are exposed by a GetXXX function, allowing
+// them to be accessed or sent messages.
+
+// CFrame is responsible for creating a "frame" window. This window has a
+// menu and and several child windows, including a toolbar (usualy hosted
+// within a rebar), a status bar, and a view positioned over the frame
+// window's non-client area. The "view" window is a seperate CWnd object
+// assigned to the frame with the SetView function.
+
+// When compiling an application with these classes, it will need to be linked
+// with Comctl32.lib.
+
+// To create a SDI frame application, inherit a CMainFrame class from CFrame.
+// Use the Frame sample application as the starting point for your own frame
+// applications.
+// Refer to the Notepad and Scribble samples for examples on how to use these
+// classes to create a frame application.
+
+
+#ifndef _WIN32XX_FRAME_H_
+#define _WIN32XX_FRAME_H_
+
+#include "wincore.h"
+#include "dialog.h"
+#include "gdi.h"
+#include "statusbar.h"
+#include "toolbar.h"
+#include "rebar.h"
+#include "default_resource.h"
+
+#ifndef RBN_MINMAX
+ #define RBN_MINMAX (RBN_FIRST - 21)
+#endif
+
+
+namespace Win32xx
+{
+
+ ////////////////////////////////////////////////
+ // Declarations for structures for themes
+ //
+ struct MenuTheme
+ {
+ BOOL UseThemes; // TRUE if themes are used
+ COLORREF clrHot1; // Colour 1 for top menu. Color of selected menu item
+ COLORREF clrHot2; // Colour 2 for top menu. Color of checkbox
+ COLORREF clrPressed1; // Colour 1 for pressed top menu and side bar
+ COLORREF clrPressed2; // Colour 2 for pressed top menu and side bar
+ COLORREF clrOutline; // Colour for border outline
+ };
+
+
+ // Forward declaration of CFrame. Its defined later.
+ class CFrame;
+
+
+ ////////////////////////////////////
+ // Declaration of the CMenuBar class
+ //
+ class CMenuBar : public CToolBar
+ {
+ friend class CFrame;
+
+ public:
+ CMenuBar();
+ virtual ~CMenuBar();
+ virtual void SetMenu(HMENU hMenu);
+ virtual void SetMenuBarTheme(MenuTheme& Theme);
+
+ HMENU GetMenu() const {return m_hTopMenu;}
+ MenuTheme& GetMenuBarTheme() {return m_ThemeMenu;}
+
+ protected:
+ //Overridables
+ virtual void OnCreate();
+ virtual LRESULT OnCustomDraw(NMHDR* pNMHDR);
+ virtual void OnKeyDown(WPARAM wParam, LPARAM lParam);
+ virtual void OnLButtonDown(WPARAM wParam, LPARAM lParam);
+ virtual void OnLButtonUp(WPARAM wParam, LPARAM lParam);
+ virtual void OnMenuChar(WPARAM wParam, LPARAM lParam);
+ virtual BOOL OnMenuInput(UINT uMsg, WPARAM wParam, LPARAM lParam);
+ virtual void OnMouseLeave();
+ virtual void OnMouseMove(WPARAM wParam, LPARAM lParam);
+ virtual LRESULT OnNotifyReflect(WPARAM wParam, LPARAM lParam);
+ virtual void OnSysCommand(WPARAM wParam, LPARAM lParam);
+ virtual void OnWindowPosChanged();
+ virtual void PreCreate(CREATESTRUCT &cs);
+ virtual void PreRegisterClass(WNDCLASS &wc);
+ virtual LRESULT WndProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam);
+
+ private:
+ CMenuBar(const CMenuBar&); // Disable copy construction
+ CMenuBar& operator = (const CMenuBar&); // Disable assignment operator
+ void DoAltKey(WORD KeyCode);
+ void DoPopupMenu();
+ void DrawAllMDIButtons(CDC& DrawDC);
+ void DrawMDIButton(CDC& DrawDC, int iButton, UINT uState);
+ void ExitMenu();
+ HWND GetActiveMDIChild();
+ void GrabFocus();
+ BOOL IsMDIChildMaxed() const;
+ BOOL IsMDIFrame() const;
+ void ReleaseFocus();
+ void SetHotItem(int nHot);
+ static LRESULT CALLBACK StaticMsgHook(int nCode, WPARAM wParam, LPARAM lParam);
+
+ enum MDIButtonType
+ {
+ MDI_MIN = 0,
+ MDI_RESTORE = 1,
+ MDI_CLOSE = 2,
+ };
+
+ BOOL m_bExitAfter; // Exit after Popup menu ends
+ BOOL m_bKeyMode; // keyboard navigation mode
+ BOOL m_bMenuActive; // popup menu active
+ BOOL m_bSelPopup; // a popup (cascade) menu is selected
+ HMENU m_hPopupMenu; // handle to the popup menu
+ HMENU m_hSelMenu; // handle to the casceded popup menu
+ HMENU m_hTopMenu; // handle to the top level menu
+ HWND m_hPrevFocus; // handle to window which had focus
+ CRect m_MDIRect[3]; // array of CRect for MDI buttons
+ int m_nHotItem; // hot item
+ int m_nMDIButton; // the MDI button (MDIButtonType) pressed
+ CPoint m_OldMousePos; // old Mouse position
+ MenuTheme m_ThemeMenu; // Theme structure
+ CFrame* m_pFrame; // Pointer to the frame
+
+ }; // class CMenuBar
+
+
+
+ //////////////////////////////////
+ // Declaration of the CFrame class
+ //
+ class CFrame : public CWnd
+ {
+ friend class CMenuBar;
+
+ struct ItemData
+ // Each Dropdown menu item has this data
+ {
+ HMENU hMenu;
+ UINT nPos;
+ UINT fType;
+ std::vector<TCHAR> vItemText;
+ HMENU hSubMenu;
+
+ ItemData() : hMenu(0), nPos(0), fType(0), hSubMenu(0) { vItemText.assign(MAX_MENU_STRING, _T('\0')); }
+ LPTSTR GetItemText() {return &vItemText[0];}
+ };
+
+ typedef Shared_Ptr<ItemData> ItemDataPtr;
+
+ public:
+ CFrame();
+ virtual ~CFrame();
+
+ // Override these functions as required
+ virtual void AdjustFrameRect(RECT rcView) const;
+ virtual CRect GetViewRect() const;
+ virtual BOOL IsMDIFrame() const { return FALSE; }
+ virtual void SetStatusIndicators();
+ virtual void SetStatusText();
+ virtual void RecalcLayout();
+ virtual MenuTheme& GetMenuTheme() const { return (MenuTheme&) m_ThemeMenu; }
+ virtual ReBarTheme& GetReBarTheme() const { return (ReBarTheme&)GetReBar().GetReBarTheme(); }
+ virtual ToolBarTheme& GetToolBarTheme() const { return (ToolBarTheme&)GetToolBar().GetToolBarTheme(); }
+
+ // Virtual Attributes
+ // If you need to modify the default behaviour of the menubar, rebar,
+ // statusbar or toolbar, inherit from those classes, and override
+ // the following attribute functions.
+ virtual CMenuBar& GetMenuBar() const { return (CMenuBar&)m_MenuBar; }
+ virtual CReBar& GetReBar() const { return (CReBar&)m_ReBar; }
+ virtual CStatusBar& GetStatusBar() const { return (CStatusBar&)m_StatusBar; }
+ virtual CToolBar& GetToolBar() const { return (CToolBar&)m_ToolBar; }
+
+ // These functions aren't virtual, and shouldn't be overridden
+ HACCEL GetFrameAccel() const { return m_hAccel; }
+ CMenu& GetFrameMenu() const { return (CMenu&)m_Menu; }
+ std::vector<tString> GetMRUEntries() const { return m_vMRUEntries; }
+ tString GetRegistryKeyName() const { return m_tsKeyName; }
+ CWnd* GetView() const { return m_pView; }
+ tString GetMRUEntry(UINT nIndex);
+ void SetFrameMenu(INT ID_MENU);
+ void SetFrameMenu(HMENU hMenu);
+ void SetMenuTheme(MenuTheme& Theme);
+ void SetView(CWnd& wndView);
+ BOOL IsMenuBarUsed() const { return (GetMenuBar() != 0); }
+ BOOL IsReBarSupported() const { return (GetComCtlVersion() >= 470); }
+ BOOL IsReBarUsed() const { return (GetReBar() != 0); }
+
+ protected:
+ // Override these functions as required
+ virtual BOOL AddMenuIcon(int nID_MenuItem, HICON hIcon, int cx = 16, int cy = 16);
+ virtual UINT AddMenuIcons(const std::vector<UINT>& MenuData, COLORREF crMask, UINT ToolBarID, UINT ToolBarDisabledID);
+ virtual void AddMenuBarBand();
+ virtual void AddMRUEntry(LPCTSTR szMRUEntry);
+ virtual void AddToolBarBand(CToolBar& TB, DWORD dwStyle, UINT nID);
+ virtual void AddToolBarButton(UINT nID, BOOL bEnabled = TRUE, LPCTSTR szText = 0);
+ virtual void CreateToolBar();
+ virtual void DrawCheckmark(LPDRAWITEMSTRUCT pdis, CDC& DrawDC);
+ virtual void DrawMenuIcon(LPDRAWITEMSTRUCT pdis, CDC& DrawDC, BOOL bDisabled);
+ virtual void DrawMenuText(CDC& DrawDC, LPCTSTR ItemText, CRect& rc, COLORREF colorText);
+ virtual int GetMenuItemPos(HMENU hMenu, LPCTSTR szItem);
+ virtual BOOL LoadRegistrySettings(LPCTSTR szKeyName);
+ virtual BOOL LoadRegistryMRUSettings(UINT nMaxMRU = 0);
+ virtual void OnActivate(WPARAM wParam, LPARAM lParam);
+ virtual void OnClose();
+ virtual void OnCreate();
+ virtual void OnDestroy();
+ virtual LRESULT OnDrawItem(WPARAM wParam, LPARAM lParam);
+ virtual void OnExitMenuLoop();
+ virtual void OnHelp();
+ virtual void OnInitMenuPopup(WPARAM wParam, LPARAM lParam);
+ virtual LRESULT OnMeasureItem(WPARAM wParam, LPARAM lParam);
+ virtual LRESULT OnMenuChar(WPARAM wParam, LPARAM lParam);
+ virtual void OnMenuSelect(WPARAM wParam, LPARAM lParam);
+ virtual LRESULT OnNotify(WPARAM wParam, LPARAM lParam);
+ virtual void OnSetFocus();
+ virtual void OnSysColorChange();
+ virtual LRESULT OnSysCommand(WPARAM wParam, LPARAM lParam);
+ virtual void OnTimer(WPARAM wParam);
+ virtual void OnViewStatusBar();
+ virtual void OnViewToolBar();
+ virtual void PreCreate(CREATESTRUCT& cs);
+ virtual void PreRegisterClass(WNDCLASS &wc);
+ virtual void RemoveMRUEntry(LPCTSTR szMRUEntry);
+ virtual BOOL SaveRegistrySettings();
+ virtual void SetMenuBarBandSize();
+ virtual UINT SetMenuIcons(const std::vector<UINT>& MenuData, COLORREF crMask, UINT ToolBarID, UINT ToolBarDisabledID);
+ virtual void SetupToolBar();
+ virtual void SetTheme();
+ virtual void SetToolBarImages(COLORREF crMask, UINT ToolBarID, UINT ToolBarHotID, UINT ToolBarDisabledID);
+ virtual void ShowMenu(BOOL bShow);
+ virtual void ShowStatusBar(BOOL bShow);
+ virtual void ShowToolBar(BOOL bShow);
+ virtual void UpdateMRUMenu();
+ virtual LRESULT WndProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam);
+
+ enum Constants
+ {
+ ID_STATUS_TIMER = 1,
+ POST_TEXT_GAP = 16, // for owner draw menu item
+ };
+
+ tString m_tsStatusText; // TCHAR std::string for status text
+ BOOL m_bShowIndicatorStatus; // set to TRUE to see indicators in status bar
+ BOOL m_bShowMenuStatus; // set to TRUE to see menu and toolbar updates in status bar
+ BOOL m_bUseReBar; // set to TRUE if ReBars are to be used
+ BOOL m_bUseThemes; // set to TRUE if themes are to be used
+ BOOL m_bUpdateTheme; // set to TRUE to run SetThemes when theme changes
+ BOOL m_bUseToolBar; // set to TRUE if the toolbar is used
+ BOOL m_bUseCustomDraw; // set to TRUE to perform custom drawing on menu items
+ BOOL m_bShowStatusBar; // A flag to indicate if the StatusBar should be displayed
+ BOOL m_bShowToolBar; // A flag to indicate if the ToolBar should be displayed
+ MenuTheme m_ThemeMenu; // Theme structure for popup menus
+ HIMAGELIST m_himlMenu; // Imagelist of menu icons
+ HIMAGELIST m_himlMenuDis; // Imagelist of disabled menu icons
+
+ private:
+ CFrame(const CFrame&); // Disable copy construction
+ CFrame& operator = (const CFrame&); // Disable assignment operator
+ void LoadCommonControls();
+
+ std::vector<ItemDataPtr> m_vMenuItemData;// vector of ItemData pointers
+ std::vector<UINT> m_vMenuIcons; // vector of menu icon resource IDs
+ std::vector<tString> m_vMRUEntries; // Vector of tStrings for MRU entires
+ CDialog m_AboutDialog; // Help about dialog
+ CMenuBar m_MenuBar; // CMenuBar object
+ CReBar m_ReBar; // CReBar object
+ CStatusBar m_StatusBar; // CStatusBar object
+ CToolBar m_ToolBar; // CToolBar object
+ CMenu m_Menu; // handle to the frame menu
+ HACCEL m_hAccel; // handle to the frame's accelerator table
+ CWnd* m_pView; // pointer to the View CWnd object
+ LPCTSTR m_OldStatus[3]; // Array of TCHAR pointers;
+ tString m_tsKeyName; // TCHAR std::string for Registry key name
+ tString m_tsTooltip; // TCHAR std::string for tool tips
+ UINT m_nMaxMRU; // maximum number of MRU entries
+ CRect m_rcPosition; // CRect of the starting window position
+ HWND m_hOldFocus; // The window which had focus prior to the app'a deactivation
+ int m_nOldID; // The previous ToolBar ID displayed in the statusbar
+
+ }; // class CFrame
+
+}
+
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+namespace Win32xx
+{
+
+ /////////////////////////////////////
+ // Definitions for the CMenuBar class
+ //
+ inline CMenuBar::CMenuBar()
+ {
+ m_bExitAfter = FALSE;
+ m_hTopMenu = NULL;
+ m_nHotItem = -1;
+ m_bSelPopup = FALSE;
+ m_hSelMenu = NULL;
+ m_bMenuActive = FALSE;
+ m_bKeyMode = FALSE;
+ m_hPrevFocus = NULL;
+ m_nMDIButton = 0;
+ m_hPopupMenu = 0;
+
+ ZeroMemory(&m_ThemeMenu, sizeof(MenuTheme));
+ }
+
+ inline CMenuBar::~CMenuBar()
+ {
+ }
+
+ inline void CMenuBar::DoAltKey(WORD KeyCode)
+ {
+ //Handle key pressed with Alt held down
+ UINT ID;
+ if (SendMessage(TB_MAPACCELERATOR, KeyCode, (LPARAM) &ID))
+ {
+ GrabFocus();
+ m_bKeyMode = TRUE;
+ SetHotItem(ID);
+ m_bMenuActive = TRUE;
+ PostMessage(UWM_POPUPMENU, 0L, 0L);
+ }
+ else
+ ::MessageBeep(MB_OK);
+ }
+
+ inline void CMenuBar::DoPopupMenu()
+ {
+ if (m_bKeyMode)
+ // Simulate a down arrow key press
+ PostMessage(WM_KEYDOWN, VK_DOWN, 0L);
+
+ m_bKeyMode = FALSE;
+ m_bExitAfter = FALSE;
+ m_OldMousePos = GetCursorPos();
+
+ HWND hMaxMDIChild = NULL;
+ if (IsMDIChildMaxed())
+ hMaxMDIChild = GetActiveMDIChild();
+
+ // Load the submenu
+ int nMaxedOffset = IsMDIChildMaxed()? 1:0;
+ m_hPopupMenu = ::GetSubMenu(m_hTopMenu, m_nHotItem - nMaxedOffset);
+ if (IsMDIChildMaxed() && (0 == m_nHotItem) )
+ m_hPopupMenu = ::GetSystemMenu(hMaxMDIChild, FALSE);
+
+ // Retrieve the bounding rectangle for the toolbar button
+ CRect rc = GetItemRect(m_nHotItem);
+
+ // convert rectangle to desktop coordinates
+ ClientToScreen(rc);
+
+ // Position popup above toolbar if it won't fit below
+ TPMPARAMS tpm;
+ tpm.cbSize = sizeof(TPMPARAMS);
+ tpm.rcExclude = rc;
+
+ // Set the hot button
+ SendMessage(TB_SETHOTITEM, m_nHotItem, 0L);
+ SendMessage(TB_PRESSBUTTON, m_nHotItem, MAKELONG(TRUE, 0));
+
+ m_bSelPopup = FALSE;
+ m_hSelMenu = NULL;
+ m_bMenuActive = TRUE;
+
+ // We hook mouse input to process mouse and keyboard input during
+ // the popup menu. Messages are sent to StaticMsgHook.
+
+ // Remove any remaining hook first
+ TLSData* pTLSData = (TLSData*)::TlsGetValue(GetApp()->GetTlsIndex());
+ pTLSData->pMenuBar = this;
+ if (pTLSData->hHook != NULL)
+ ::UnhookWindowsHookEx(pTLSData->hHook);
+
+ // Hook messages about to be processed by the shortcut menu
+ pTLSData->hHook = ::SetWindowsHookEx(WH_MSGFILTER, (HOOKPROC)StaticMsgHook, NULL, ::GetCurrentThreadId());
+
+ // Display the shortcut menu
+ BOOL bRightToLeft = FALSE;
+
+#if defined(WINVER) && defined (WS_EX_LAYOUTRTL) && (WINVER >= 0x0500)
+ bRightToLeft = ((GetAncestor()->GetWindowLongPtr(GWL_EXSTYLE)) & WS_EX_LAYOUTRTL);
+#endif
+
+ int xPos = bRightToLeft? rc.right : rc.left;
+ UINT nID = ::TrackPopupMenuEx(m_hPopupMenu, TPM_LEFTALIGN | TPM_LEFTBUTTON | TPM_VERTICAL,
+ xPos, rc.bottom, m_hWnd, &tpm);
+
+ // We get here once the TrackPopupMenuEx has ended
+ m_bMenuActive = FALSE;
+
+ // Remove the message hook
+ ::UnhookWindowsHookEx(pTLSData->hHook);
+ pTLSData->hHook = NULL;
+
+ // Process MDI Child system menu
+ if (IsMDIChildMaxed())
+ {
+ if (::GetSystemMenu(hMaxMDIChild, FALSE) == m_hPopupMenu )
+ {
+ if (nID)
+ ::SendMessage(hMaxMDIChild, WM_SYSCOMMAND, nID, 0L);
+ }
+ }
+
+ // Resestablish Focus
+ if (m_bKeyMode)
+ GrabFocus();
+ }
+
+ inline void CMenuBar::DrawAllMDIButtons(CDC& DrawDC)
+ {
+ if (!IsMDIFrame())
+ return;
+
+ if (IsMDIChildMaxed())
+ {
+ int cx = GetSystemMetrics(SM_CXSMICON);
+ int cy = GetSystemMetrics(SM_CYSMICON);
+ CRect rc = GetClientRect();
+ int gap = 4;
+ rc.right -= gap;
+
+ // Assign values to each element of the CRect array
+ for (int i = 0 ; i < 3 ; ++i)
+ {
+ int left = rc.right - (i+1)*cx - gap*(i+1);
+ int top = rc.bottom/2 - cy/2;
+ int right = rc.right - i*cx - gap*(i+1);
+ int bottom = rc.bottom/2 + cy/2;
+ ::SetRect(&m_MDIRect[2 - i], left, top, right, bottom);
+ }
+
+ // Hide the MDI button if it won't fit
+ for (int k = 0 ; k <= 2 ; ++k)
+ {
+
+ if (m_MDIRect[k].left < GetMaxSize().cx)
+ {
+ ::SetRectEmpty(&m_MDIRect[k]);
+ }
+ }
+
+ DrawMDIButton(DrawDC, MDI_MIN, 0);
+ DrawMDIButton(DrawDC, MDI_RESTORE, 0);
+ DrawMDIButton(DrawDC, MDI_CLOSE, 0);
+ }
+ }
+
+ inline void CMenuBar::DrawMDIButton(CDC& DrawDC, int iButton, UINT uState)
+ {
+ if (!IsRectEmpty(&m_MDIRect[iButton]))
+ {
+ switch (uState)
+ {
+ case 0:
+ {
+ // Draw a grey outline
+ DrawDC.CreatePen(PS_SOLID, 1, GetSysColor(COLOR_BTNFACE));
+ DrawDC.MoveTo(m_MDIRect[iButton].left, m_MDIRect[iButton].bottom);
+ DrawDC.LineTo(m_MDIRect[iButton].right, m_MDIRect[iButton].bottom);
+ DrawDC.LineTo(m_MDIRect[iButton].right, m_MDIRect[iButton].top);
+ DrawDC.LineTo(m_MDIRect[iButton].left, m_MDIRect[iButton].top);
+ DrawDC.LineTo(m_MDIRect[iButton].left, m_MDIRect[iButton].bottom);
+ }
+ break;
+ case 1:
+ {
+ // Draw outline, white at top, black on bottom
+ DrawDC.CreatePen(PS_SOLID, 1, RGB(0, 0, 0));
+ DrawDC.MoveTo(m_MDIRect[iButton].left, m_MDIRect[iButton].bottom);
+ DrawDC.LineTo(m_MDIRect[iButton].right, m_MDIRect[iButton].bottom);
+ DrawDC.LineTo(m_MDIRect[iButton].right, m_MDIRect[iButton].top);
+ DrawDC.CreatePen(PS_SOLID, 1, RGB(255, 255, 255));
+ DrawDC.LineTo(m_MDIRect[iButton].left, m_MDIRect[iButton].top);
+ DrawDC.LineTo(m_MDIRect[iButton].left, m_MDIRect[iButton].bottom);
+ }
+
+ break;
+ case 2:
+ {
+ // Draw outline, black on top, white on bottom
+ DrawDC.CreatePen(PS_SOLID, 1, RGB(255, 255, 255));
+ DrawDC.MoveTo(m_MDIRect[iButton].left, m_MDIRect[iButton].bottom);
+ DrawDC.LineTo(m_MDIRect[iButton].right, m_MDIRect[iButton].bottom);
+ DrawDC.LineTo(m_MDIRect[iButton].right, m_MDIRect[iButton].top);
+ DrawDC.CreatePen(PS_SOLID, 1, RGB(0, 0, 0));
+ DrawDC.LineTo(m_MDIRect[iButton].left, m_MDIRect[iButton].top);
+ DrawDC.LineTo(m_MDIRect[iButton].left, m_MDIRect[iButton].bottom);
+ }
+ break;
+ }
+
+ DrawDC.CreatePen(PS_SOLID, 1, RGB(0, 0, 0));
+
+ switch (iButton)
+ {
+ case MDI_MIN:
+ // Manually Draw Minimise button
+ DrawDC.MoveTo(m_MDIRect[0].left + 4, m_MDIRect[0].bottom -4);
+ DrawDC.LineTo(m_MDIRect[0].right - 4, m_MDIRect[0].bottom - 4);
+
+ DrawDC.MoveTo(m_MDIRect[0].left + 4, m_MDIRect[0].bottom -5);
+ DrawDC.LineTo(m_MDIRect[0].right - 4, m_MDIRect[0].bottom - 5);
+ break;
+ case MDI_RESTORE:
+ // Manually Draw Restore Button
+ DrawDC.MoveTo(m_MDIRect[1].left + 3, m_MDIRect[1].top + 7);
+ DrawDC.LineTo(m_MDIRect[1].left + 3, m_MDIRect[1].bottom -4);
+ DrawDC.LineTo(m_MDIRect[1].right - 6, m_MDIRect[1].bottom -4);
+ DrawDC.LineTo(m_MDIRect[1].right - 6, m_MDIRect[1].top + 7);
+ DrawDC.LineTo(m_MDIRect[1].left + 3, m_MDIRect[1].top + 7);
+
+ DrawDC.MoveTo(m_MDIRect[1].left + 3, m_MDIRect[1].top + 8);
+ DrawDC.LineTo(m_MDIRect[1].right - 6, m_MDIRect[1].top + 8);
+
+ DrawDC.MoveTo(m_MDIRect[1].left + 5, m_MDIRect[1].top + 7);
+ DrawDC.LineTo(m_MDIRect[1].left + 5, m_MDIRect[1].top + 4);
+ DrawDC.LineTo(m_MDIRect[1].right - 4, m_MDIRect[1].top + 4);
+ DrawDC.LineTo(m_MDIRect[1].right - 4, m_MDIRect[1].bottom -6);
+ DrawDC.LineTo(m_MDIRect[1].right - 6, m_MDIRect[1].bottom -6);
+
+ DrawDC.MoveTo(m_MDIRect[1].left + 5, m_MDIRect[1].top + 5);
+ DrawDC.LineTo(m_MDIRect[1].right - 4, m_MDIRect[1].top + 5);
+ break;
+ case MDI_CLOSE:
+ // Manually Draw Close Button
+ DrawDC.MoveTo(m_MDIRect[2].left + 4, m_MDIRect[2].top +5);
+ DrawDC.LineTo(m_MDIRect[2].right - 4, m_MDIRect[2].bottom -3);
+
+ DrawDC.MoveTo(m_MDIRect[2].left + 5, m_MDIRect[2].top +5);
+ DrawDC.LineTo(m_MDIRect[2].right - 4, m_MDIRect[2].bottom -4);
+
+ DrawDC.MoveTo(m_MDIRect[2].left + 4, m_MDIRect[2].top +6);
+ DrawDC.LineTo(m_MDIRect[2].right - 5, m_MDIRect[2].bottom -3);
+
+ DrawDC.MoveTo(m_MDIRect[2].right -5, m_MDIRect[2].top +5);
+ DrawDC.LineTo(m_MDIRect[2].left + 3, m_MDIRect[2].bottom -3);
+
+ DrawDC.MoveTo(m_MDIRect[2].right -5, m_MDIRect[2].top +6);
+ DrawDC.LineTo(m_MDIRect[2].left + 4, m_MDIRect[2].bottom -3);
+
+ DrawDC.MoveTo(m_MDIRect[2].right -6, m_MDIRect[2].top +5);
+ DrawDC.LineTo(m_MDIRect[2].left + 3, m_MDIRect[2].bottom -4);
+ break;
+ }
+ }
+ }
+
+ inline void CMenuBar::ExitMenu()
+ {
+ ReleaseFocus();
+ m_bKeyMode = FALSE;
+ m_bMenuActive = FALSE;
+ SendMessage(TB_PRESSBUTTON, m_nHotItem, (LPARAM) MAKELONG (FALSE, 0));
+ SetHotItem(-1);
+
+ CPoint pt = GetCursorPos();
+ ScreenToClient(pt);
+
+ // Update mouse mouse position for hot tracking
+ SendMessage(WM_MOUSEMOVE, 0L, MAKELONG(pt.x, pt.y));
+ }
+
+ inline HWND CMenuBar::GetActiveMDIChild()
+ {
+ HWND hwndMDIChild = NULL;
+ if (IsMDIFrame())
+ {
+ hwndMDIChild = (HWND)::SendMessage(m_pFrame->GetView()->GetHwnd(), WM_MDIGETACTIVE, 0L, 0L);
+ }
+
+ return hwndMDIChild;
+ }
+
+ inline void CMenuBar::GrabFocus()
+ {
+ if (::GetFocus() != m_hWnd)
+ m_hPrevFocus = ::SetFocus(m_hWnd);
+ ::SetCapture(m_hWnd);
+ ::SetCursor(::LoadCursor(NULL, IDC_ARROW));
+ }
+
+ inline BOOL CMenuBar::IsMDIChildMaxed() const
+ {
+ BOOL bMaxed = FALSE;
+
+ if (IsMDIFrame() && m_pFrame->GetView()->IsWindow())
+ {
+ m_pFrame->GetView()->SendMessage(WM_MDIGETACTIVE, 0L, (LPARAM)&bMaxed);
+ }
+
+ return bMaxed;
+ }
+
+ inline BOOL CMenuBar::IsMDIFrame() const
+ {
+ return (m_pFrame->IsMDIFrame());
+ }
+
+ inline void CMenuBar::OnMenuChar(WPARAM wParam, LPARAM lParam)
+ {
+ UNREFERENCED_PARAMETER(lParam);
+
+ if (!m_bMenuActive)
+ DoAltKey(LOWORD(wParam));
+ }
+
+ inline void CMenuBar::OnCreate()
+ {
+ // We must send this message before sending the TB_ADDBITMAP or TB_ADDBUTTONS message
+ SendMessage(TB_BUTTONSTRUCTSIZE, (WPARAM)sizeof(TBBUTTON), 0L);
+
+ m_pFrame = (CFrame*)GetAncestor();
+ assert(m_pFrame);
+ }
+
+ inline LRESULT CMenuBar::OnCustomDraw(NMHDR* pNMHDR)
+ // CustomDraw is used to render the MenuBar's toolbar buttons
+ {
+ if (m_ThemeMenu.UseThemes)
+ {
+ LPNMTBCUSTOMDRAW lpNMCustomDraw = (LPNMTBCUSTOMDRAW)pNMHDR;
+
+ switch (lpNMCustomDraw->nmcd.dwDrawStage)
+ {
+ // Begin paint cycle
+ case CDDS_PREPAINT:
+ // Send NM_CUSTOMDRAW item draw, and post-paint notification messages.
+ return CDRF_NOTIFYITEMDRAW | CDRF_NOTIFYPOSTPAINT ;
+
+ // An item is about to be drawn
+ case CDDS_ITEMPREPAINT:
+ {
+ CDC* pDrawDC = FromHandle(lpNMCustomDraw->nmcd.hdc);
+ CRect rcRect = lpNMCustomDraw->nmcd.rc;
+ int nState = lpNMCustomDraw->nmcd.uItemState;
+ DWORD dwItem = (DWORD)lpNMCustomDraw->nmcd.dwItemSpec;
+
+ // Leave a pixel gap above and below the drawn rectangle
+ if (IsAeroThemed())
+ rcRect.InflateRect(0, -2);
+ else
+ rcRect.InflateRect(0, -1);
+
+ if (IsMDIChildMaxed() && (0 == dwItem))
+ // Draw over MDI Max button
+ {
+ HICON hIcon = (HICON)::SendMessage(GetActiveMDIChild(), WM_GETICON, ICON_SMALL, 0L);
+ if (NULL == hIcon)
+ hIcon = ::LoadIcon(NULL, IDI_APPLICATION);
+
+ int cx = ::GetSystemMetrics (SM_CXSMICON);
+ int cy = ::GetSystemMetrics (SM_CYSMICON);
+ int y = 1 + (GetWindowRect().Height() - cy)/2;
+ int x = (rcRect.Width() - cx)/2;
+ pDrawDC->DrawIconEx(x, y, hIcon, cx, cy, 0, NULL, DI_NORMAL);
+
+ pDrawDC->Detach(); // Optional, deletes GDI objects sooner
+ return CDRF_SKIPDEFAULT; // No further drawing
+ }
+
+ else if (nState & (CDIS_HOT | CDIS_SELECTED))
+ {
+ if ((nState & CDIS_SELECTED) || (GetButtonState(dwItem) & TBSTATE_PRESSED))
+ {
+ pDrawDC->GradientFill(m_ThemeMenu.clrPressed1, m_ThemeMenu.clrPressed2, rcRect, FALSE);
+ }
+ else if (nState & CDIS_HOT)
+ {
+ pDrawDC->GradientFill(m_ThemeMenu.clrHot1, m_ThemeMenu.clrHot2, rcRect, FALSE);
+ }
+
+ // Draw border
+ pDrawDC->CreatePen(PS_SOLID, 1, m_ThemeMenu.clrOutline);
+ pDrawDC->MoveTo(rcRect.left, rcRect.bottom);
+ pDrawDC->LineTo(rcRect.left, rcRect.top);
+ pDrawDC->LineTo(rcRect.right-1, rcRect.top);
+ pDrawDC->LineTo(rcRect.right-1, rcRect.bottom);
+ pDrawDC->MoveTo(rcRect.right-1, rcRect.bottom);
+ pDrawDC->LineTo(rcRect.left, rcRect.bottom);
+
+ TCHAR str[80] = _T("");
+ int nLength = (int)SendMessage(TB_GETBUTTONTEXT, lpNMCustomDraw->nmcd.dwItemSpec, 0L);
+ if ((nLength > 0) && (nLength < 80))
+ SendMessage(TB_GETBUTTONTEXT, lpNMCustomDraw->nmcd.dwItemSpec, (LPARAM)str);
+
+ // Draw highlight text
+ pDrawDC->SelectObject(GetFont());
+ rcRect.bottom += 1;
+ int iMode = pDrawDC->SetBkMode(TRANSPARENT);
+ pDrawDC->DrawText(str, lstrlen(str), rcRect, DT_VCENTER | DT_CENTER | DT_SINGLELINE);
+
+ pDrawDC->SetBkMode(iMode);
+ pDrawDC->Detach(); // Optional, deletes GDI objects sooner
+ return CDRF_SKIPDEFAULT; // No further drawing
+ }
+ }
+ return CDRF_DODEFAULT ; // Do default drawing
+
+ // Painting cycle has completed
+ case CDDS_POSTPAINT:
+ // Draw MDI Minimise, Restore and Close buttons
+ {
+ CDC* pDrawDC = FromHandle(lpNMCustomDraw->nmcd.hdc);
+ DrawAllMDIButtons(*pDrawDC);
+ pDrawDC->Detach(); // Optional, deletes GDI objects sooner
+ }
+ break;
+ }
+ }
+ return 0L;
+ }
+
+ inline void CMenuBar::OnKeyDown(WPARAM wParam, LPARAM lParam)
+ {
+ UNREFERENCED_PARAMETER(lParam);
+
+ switch (wParam)
+ {
+ case VK_ESCAPE:
+ ExitMenu();
+ break;
+
+ case VK_SPACE:
+ ExitMenu();
+ // Bring up the system menu
+ GetAncestor()->PostMessage(WM_SYSCOMMAND, SC_KEYMENU, VK_SPACE);
+ break;
+
+ // Handle VK_DOWN,VK_UP and VK_RETURN together
+ case VK_DOWN:
+ case VK_UP:
+ case VK_RETURN:
+ // Always use PostMessage for USER_POPUPMENU (not SendMessage)
+ PostMessage(UWM_POPUPMENU, 0L, 0L);
+ break;
+
+ case VK_LEFT:
+ // Move left to next topmenu item
+ (m_nHotItem > 0)? SetHotItem(m_nHotItem -1) : SetHotItem(GetButtonCount()-1);
+ break;
+
+ case VK_RIGHT:
+ // Move right to next topmenu item
+ (m_nHotItem < GetButtonCount() -1)? SetHotItem(m_nHotItem +1) : SetHotItem(0);
+ break;
+
+ default:
+ // Handle Accelerator keys with Alt toggled down
+ if (m_bKeyMode)
+ {
+ UINT ID;
+ if (SendMessage(TB_MAPACCELERATOR, wParam, (LPARAM) &ID))
+ {
+ m_nHotItem = ID;
+ PostMessage(UWM_POPUPMENU, 0L, 0L);
+ }
+ else
+ ::MessageBeep(MB_OK);
+ }
+ break;
+ } // switch (wParam)
+ }
+
+ inline void CMenuBar::OnLButtonDown(WPARAM wParam, LPARAM lParam)
+ {
+ UNREFERENCED_PARAMETER(wParam);
+
+ GrabFocus();
+ m_nMDIButton = 0;
+ CPoint pt;
+
+ pt.x = GET_X_LPARAM(lParam);
+ pt.y = GET_Y_LPARAM(lParam);
+
+ if (IsMDIFrame())
+ {
+ if (IsMDIChildMaxed())
+ {
+ CClientDC MenuBarDC(this);
+ m_nMDIButton = -1;
+
+ if (m_MDIRect[0].PtInRect(pt)) m_nMDIButton = 0;
+ if (m_MDIRect[1].PtInRect(pt)) m_nMDIButton = 1;
+ if (m_MDIRect[2].PtInRect(pt)) m_nMDIButton = 2;
+
+ if (m_nMDIButton >= 0)
+ {
+ DrawMDIButton(MenuBarDC, MDI_MIN, (0 == m_nMDIButton)? 2 : 0);
+ DrawMDIButton(MenuBarDC, MDI_RESTORE, (1 == m_nMDIButton)? 2 : 0);
+ DrawMDIButton(MenuBarDC, MDI_CLOSE, (2 == m_nMDIButton)? 2 : 0);
+ }
+
+ // Bring up the MDI Child window's system menu when the icon is pressed
+ if (0 == HitTest())
+ {
+ m_nHotItem = 0;
+ PostMessage(UWM_POPUPMENU, 0L, 0L);
+ }
+ }
+ }
+ }
+
+ inline void CMenuBar::OnLButtonUp(WPARAM wParam, LPARAM lParam)
+ {
+ UNREFERENCED_PARAMETER(wParam);
+ CPoint pt;
+ pt.x = GET_X_LPARAM(lParam);
+ pt.y = GET_Y_LPARAM(lParam);
+
+ if (IsMDIFrame())
+ {
+ HWND MDIClient = m_pFrame->GetView()->GetHwnd();
+ HWND MDIChild = GetActiveMDIChild();
+
+ if (IsMDIChildMaxed())
+ {
+ CPoint pt = GetCursorPos();
+ ScreenToClient(pt);
+
+ // Process the MDI button action when the left mouse button is up
+ if (m_MDIRect[0].PtInRect(pt))
+ {
+ if (MDI_MIN == m_nMDIButton)
+ ::ShowWindow(MDIChild, SW_MINIMIZE);
+ }
+
+ if (m_MDIRect[1].PtInRect(pt))
+ {
+ if (MDI_RESTORE == m_nMDIButton)
+ ::PostMessage(MDIClient, WM_MDIRESTORE, (WPARAM)MDIChild, 0L);
+ }
+
+ if (m_MDIRect[2].PtInRect(pt))
+ {
+ if (MDI_CLOSE == m_nMDIButton)
+ ::PostMessage(MDIChild, WM_CLOSE, 0L, 0L);
+ }
+ }
+ }
+ m_nMDIButton = 0;
+ ExitMenu();
+ }
+
+ inline BOOL CMenuBar::OnMenuInput(UINT uMsg, WPARAM wParam, LPARAM lParam)
+ // When a popup menu is active, StaticMsgHook directs all menu messages here
+ {
+ switch(uMsg)
+ {
+ case WM_KEYDOWN:
+ m_bExitAfter = FALSE;
+ {
+ switch (wParam)
+ {
+ case VK_ESCAPE:
+ // Use default processing if inside a Sub Menu
+ if ((m_hSelMenu) &&(m_hSelMenu != m_hPopupMenu))
+ return FALSE;
+
+ m_bMenuActive = FALSE;
+ m_bKeyMode = TRUE;
+ SendMessage(WM_CANCELMODE, 0L, 0L);
+ SendMessage(TB_PRESSBUTTON, m_nHotItem, MAKELONG(FALSE, 0));
+ SendMessage(TB_SETHOTITEM, m_nHotItem, 0L);
+ break;
+
+ case VK_LEFT:
+ // Use default processing if inside a Sub Menu
+ if ((m_hSelMenu) &&(m_hSelMenu != m_hPopupMenu))
+ return FALSE;
+
+ SendMessage(TB_PRESSBUTTON, m_nHotItem, MAKELONG(FALSE, 0));
+
+ // Move left to next topmenu item
+ (m_nHotItem > 0)? --m_nHotItem : m_nHotItem = GetButtonCount()-1;
+ SendMessage(WM_CANCELMODE, 0L, 0L);
+
+ // Always use PostMessage for USER_POPUPMENU (not SendMessage)
+ PostMessage(UWM_POPUPMENU, 0L, 0L);
+ PostMessage(WM_KEYDOWN, VK_DOWN, 0L);
+ break;
+
+ case VK_RIGHT:
+ // Use default processing to open Sub Menu
+ if (m_bSelPopup)
+ return FALSE;
+
+ SendMessage(TB_PRESSBUTTON, m_nHotItem, MAKELONG(FALSE, 0));
+
+ // Move right to next topmenu item
+ (m_nHotItem < GetButtonCount()-1)? ++m_nHotItem : m_nHotItem = 0;
+ SendMessage(WM_CANCELMODE, 0L, 0L);
+
+ // Always use PostMessage for USER_POPUPMENU (not SendMessage)
+ PostMessage(UWM_POPUPMENU, 0L, 0L);
+ PostMessage(WM_KEYDOWN, VK_DOWN, 0L);
+ break;
+
+ case VK_RETURN:
+ m_bExitAfter = TRUE;
+ break;
+
+ } // switch (wParam)
+
+ } // case WM_KEYDOWN
+
+ return FALSE;
+
+ case WM_CHAR:
+ m_bExitAfter = TRUE;
+ return FALSE;
+
+ case WM_LBUTTONDOWN:
+ {
+ m_bExitAfter = TRUE;
+ if (HitTest() >= 0)
+ {
+ // Cancel popup when we hit a button a second time
+ SendMessage(WM_CANCELMODE, 0L, 0L);
+ return TRUE;
+ }
+ }
+ return FALSE;
+
+ case WM_LBUTTONDBLCLK:
+ // Perform default action for DblClick on MDI Maxed icon
+ if (IsMDIChildMaxed() && (0 == HitTest()))
+ {
+ CWnd* pMDIChild = FromHandle(GetActiveMDIChild());
+ CMenu* pChildMenu = pMDIChild->GetSystemMenu(FALSE);
+
+ UINT nID = pChildMenu->GetDefaultItem(FALSE, 0);
+ if (nID)
+ pMDIChild->PostMessage(WM_SYSCOMMAND, nID, 0L);
+ }
+
+ m_bExitAfter = TRUE;
+ return FALSE;
+
+ case WM_MENUSELECT:
+ {
+ // store info about selected item
+ m_hSelMenu = (HMENU)lParam;
+ m_bSelPopup = ((HIWORD(wParam) & MF_POPUP) != 0);
+
+ // Reflect message back to the frame window
+ GetAncestor()->SendMessage(WM_MENUSELECT, wParam, lParam);
+ }
+ return TRUE;
+
+ case WM_MOUSEMOVE:
+ {
+ CPoint pt;
+ pt.x = GET_X_LPARAM(lParam);
+ pt.y = GET_Y_LPARAM(lParam);
+
+ // Skip if mouse hasn't moved
+ if ((pt.x == m_OldMousePos.x) && (pt.y == m_OldMousePos.y))
+ return FALSE;
+
+ m_OldMousePos.x = pt.x;
+ m_OldMousePos.y = pt.y;
+ ScreenToClient(pt);
+
+ // Reflect messages back to the MenuBar for hot tracking
+ SendMessage(WM_MOUSEMOVE, 0L, MAKELPARAM(pt.x, pt.y));
+ }
+ break;
+
+ }
+ return FALSE;
+ }
+
+ inline void CMenuBar::OnMouseLeave()
+ {
+ if (IsMDIFrame())
+ {
+ if (IsMDIChildMaxed())
+ {
+ CClientDC MenuBarDC(this);
+
+ DrawMDIButton(MenuBarDC, MDI_MIN, 0);
+ DrawMDIButton(MenuBarDC, MDI_RESTORE, 0);
+ DrawMDIButton(MenuBarDC, MDI_CLOSE, 0);
+ }
+ }
+ }
+
+ inline void CMenuBar::OnMouseMove(WPARAM wParam, LPARAM lParam)
+ {
+ CPoint pt;
+ pt.x = GET_X_LPARAM(lParam);
+ pt.y = GET_Y_LPARAM(lParam);
+
+ if (IsMDIFrame())
+ {
+ if (IsMDIChildMaxed())
+ {
+ CClientDC MenuBarDC(this);
+ int MDIButton = -1;
+ if (m_MDIRect[0].PtInRect(pt)) MDIButton = 0;
+ if (m_MDIRect[1].PtInRect(pt)) MDIButton = 1;
+ if (m_MDIRect[2].PtInRect(pt)) MDIButton = 2;
+
+ if (MK_LBUTTON == wParam) // mouse moved with left mouse button is held down
+ {
+ // toggle the MDI button image pressed/unpressed as required
+ if (MDIButton >= 0)
+ {
+ DrawMDIButton(MenuBarDC, MDI_MIN, ((0 == MDIButton) && (0 == m_nMDIButton))? 2 : 0);
+ DrawMDIButton(MenuBarDC, MDI_RESTORE, ((1 == MDIButton) && (1 == m_nMDIButton))? 2 : 0);
+ DrawMDIButton(MenuBarDC, MDI_CLOSE, ((2 == MDIButton) && (2 == m_nMDIButton))? 2 : 0);
+ }
+ else
+ {
+ DrawMDIButton(MenuBarDC, MDI_MIN, 0);
+ DrawMDIButton(MenuBarDC, MDI_RESTORE, 0);
+ DrawMDIButton(MenuBarDC, MDI_CLOSE, 0);
+ }
+ }
+ else // mouse moved without left mouse button held down
+ {
+ if (MDIButton >= 0)
+ {
+ DrawMDIButton(MenuBarDC, MDI_MIN, (0 == MDIButton)? 1 : 0);
+ DrawMDIButton(MenuBarDC, MDI_RESTORE, (1 == MDIButton)? 1 : 0);
+ DrawMDIButton(MenuBarDC, MDI_CLOSE, (2 == MDIButton)? 1 : 0);
+ }
+ else
+ {
+ DrawMDIButton(MenuBarDC, MDI_MIN, 0);
+ DrawMDIButton(MenuBarDC, MDI_RESTORE, 0);
+ DrawMDIButton(MenuBarDC, MDI_CLOSE, 0);
+ }
+ }
+ }
+ }
+ }
+
+ inline LRESULT CMenuBar::OnNotifyReflect(WPARAM wParam, LPARAM lParam)
+ {
+ UNREFERENCED_PARAMETER(wParam);
+
+ switch (((LPNMHDR)lParam)->code)
+ {
+ case NM_CUSTOMDRAW:
+ {
+ return OnCustomDraw((LPNMHDR) lParam);
+ }
+
+ case TBN_DROPDOWN:
+ // Always use PostMessage for USER_POPUPMENU (not SendMessage)
+ PostMessage(UWM_POPUPMENU, 0L, 0L);
+ break;
+
+ case TBN_HOTITEMCHANGE:
+ // This is the notification that a hot item change is about to occur
+ // This is used to bring up a new popup menu when required
+ {
+ CPoint pt = GetCursorPos();
+ if (this == WindowFromPoint(pt)) // MenuBar window must be on top
+ {
+ DWORD flag = ((LPNMTBHOTITEM)lParam)->dwFlags;
+ if ((flag & HICF_MOUSE) && !(flag & HICF_LEAVING))
+ {
+ int nButton = HitTest();
+ if ((m_bMenuActive) && (nButton != m_nHotItem))
+ {
+ SendMessage(TB_PRESSBUTTON, m_nHotItem, MAKELONG(FALSE, 0));
+ m_nHotItem = nButton;
+ SendMessage(WM_CANCELMODE, 0L, 0L);
+
+ //Always use PostMessage for USER_POPUPMENU (not SendMessage)
+ PostMessage(UWM_POPUPMENU, 0L, 0L);
+ }
+ m_nHotItem = nButton;
+ }
+
+ // Handle escape from popup menu
+ if ((flag & HICF_LEAVING) && m_bKeyMode)
+ {
+ m_nHotItem = ((LPNMTBHOTITEM)lParam)->idOld;
+ PostMessage(TB_SETHOTITEM, m_nHotItem, 0L);
+ }
+
+ }
+ break;
+ } //case TBN_HOTITEMCHANGE:
+
+ } // switch(((LPNMHDR)lParam)->code)
+ return 0L;
+ } // CMenuBar::OnNotify(...)
+
+ inline void CMenuBar::OnWindowPosChanged()
+ {
+ InvalidateRect(&m_MDIRect[0], TRUE);
+ InvalidateRect(&m_MDIRect[1], TRUE);
+ InvalidateRect(&m_MDIRect[2], TRUE);
+ {
+ CClientDC MenuBarDC(this);
+ DrawAllMDIButtons(MenuBarDC);
+ }
+ }
+
+ inline void CMenuBar::PreCreate(CREATESTRUCT &cs)
+ {
+ cs.style = WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | TBSTYLE_TOOLTIPS | TBSTYLE_LIST | TBSTYLE_FLAT | CCS_NODIVIDER | CCS_NORESIZE;
+ }
+
+ inline void CMenuBar::PreRegisterClass(WNDCLASS &wc)
+ {
+ // Set the Window Class
+ wc.lpszClassName = TOOLBARCLASSNAME;
+ }
+
+ inline void CMenuBar::ReleaseFocus()
+ {
+ if (m_hPrevFocus)
+ ::SetFocus(m_hPrevFocus);
+
+ m_hPrevFocus = NULL;
+ ::ReleaseCapture();
+ }
+
+ inline void CMenuBar::SetHotItem(int nHot)
+ {
+ m_nHotItem = nHot;
+ SendMessage(TB_SETHOTITEM, m_nHotItem, 0L);
+ }
+
+ inline void CMenuBar::SetMenu(HMENU hMenu)
+ {
+ assert(::IsWindow(m_hWnd));
+
+ m_hTopMenu = hMenu;
+ int nMaxedOffset = (IsMDIChildMaxed()? 1:0);
+
+ // Remove any existing buttons
+ while (SendMessage(TB_BUTTONCOUNT, 0L, 0L) > 0)
+ {
+ if(!SendMessage(TB_DELETEBUTTON, 0L, 0L))
+ break;
+ }
+
+ // Set the Bitmap size to zero
+ SendMessage(TB_SETBITMAPSIZE, 0L, MAKELPARAM(0, 0));
+
+ if (IsMDIChildMaxed())
+ {
+ // Create an extra button for the MDI child system menu
+ // Later we will custom draw the window icon over this button
+ TBBUTTON tbb = {0};
+ tbb.fsState = TBSTATE_ENABLED;
+ tbb.fsStyle = TBSTYLE_BUTTON | TBSTYLE_AUTOSIZE ;
+ tbb.iString = (INT_PTR)_T(" ");
+ SendMessage(TB_ADDBUTTONS, 1, (WPARAM)&tbb);
+ SetButtonText(0, _T(" "));
+ }
+
+ for (int i = 0 ; i < ::GetMenuItemCount(hMenu); ++i)
+ {
+ // Assign the ToolBar Button struct
+ TBBUTTON tbb = {0};
+ tbb.idCommand = i + nMaxedOffset; // Each button needs a unique ID
+ tbb.fsState = TBSTATE_ENABLED;
+ tbb.fsStyle = TBSTYLE_BUTTON | TBSTYLE_AUTOSIZE | TBSTYLE_DROPDOWN;
+ tbb.iString = (INT_PTR)_T(" ");
+ SendMessage(TB_ADDBUTTONS, 1, (WPARAM)&tbb);
+
+ // Add the menu title to the string table
+ std::vector<TCHAR> vMenuName( MAX_MENU_STRING+1, _T('\0') );
+ TCHAR* szMenuName = &vMenuName[0];
+ GetMenuString(hMenu, i, szMenuName, MAX_MENU_STRING, MF_BYPOSITION);
+ SetButtonText(i + nMaxedOffset, szMenuName);
+ }
+ }
+
+ inline void CMenuBar::SetMenuBarTheme(MenuTheme& Theme)
+ {
+ m_ThemeMenu.UseThemes = Theme.UseThemes;
+ m_ThemeMenu.clrHot1 = Theme.clrHot1;
+ m_ThemeMenu.clrHot2 = Theme.clrHot2;
+ m_ThemeMenu.clrPressed1 = Theme.clrPressed1;
+ m_ThemeMenu.clrPressed2 = Theme.clrPressed2;
+ m_ThemeMenu.clrOutline = Theme.clrOutline;
+
+ if (IsWindow())
+ Invalidate();
+ }
+
+ inline LRESULT CALLBACK CMenuBar::StaticMsgHook(int nCode, WPARAM wParam, LPARAM lParam)
+ {
+ assert(GetApp());
+ MSG* pMsg = (MSG*)lParam;
+ TLSData* pTLSData = (TLSData*)TlsGetValue(GetApp()->GetTlsIndex());
+ assert(pTLSData);
+ CMenuBar* pMenuBar = (CMenuBar*)pTLSData->pMenuBar;
+
+ if (pMenuBar && (MSGF_MENU == nCode))
+ {
+ // process menu message
+ if (pMenuBar->OnMenuInput(pMsg->message, pMsg->wParam, pMsg->lParam))
+ {
+ return TRUE;
+ }
+ }
+
+ return CallNextHookEx(pTLSData->hHook, nCode, wParam, lParam);
+ }
+
+ inline void CMenuBar::OnSysCommand(WPARAM wParam, LPARAM lParam)
+ {
+ if (SC_KEYMENU == wParam)
+ {
+ if (0 == lParam)
+ {
+ // Alt/F10 key toggled
+ GrabFocus();
+ m_bKeyMode = TRUE;
+ int nMaxedOffset = (IsMDIChildMaxed()? 1:0);
+ SetHotItem(nMaxedOffset);
+ }
+ else
+ // Handle key pressed with Alt held down
+ DoAltKey((WORD)lParam);
+ }
+ }
+
+ inline LRESULT CMenuBar::WndProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam)
+ {
+ switch (uMsg)
+ {
+ case WM_CHAR:
+ return 0L; // Discard these messages
+ case WM_DRAWITEM:
+ m_pFrame->OnDrawItem(wParam, lParam);
+ return TRUE; // handled
+ case WM_EXITMENULOOP:
+ if (m_bExitAfter)
+ ExitMenu();
+ m_pFrame->OnExitMenuLoop();
+ break;
+ case WM_INITMENUPOPUP:
+ m_pFrame->OnInitMenuPopup(wParam, lParam);
+ break;
+ case WM_KEYDOWN:
+ OnKeyDown(wParam, lParam);
+ return 0L; // Discard these messages
+ case WM_KILLFOCUS:
+ ExitMenu();
+ return 0L;
+ case WM_LBUTTONDOWN:
+ // Do default processing first
+ CallWindowProc(GetPrevWindowProc(), uMsg, wParam, lParam);
+
+ OnLButtonDown(wParam, lParam);
+ return 0L;
+ case WM_LBUTTONUP:
+ OnLButtonUp(wParam, lParam);
+ break;
+ case WM_MEASUREITEM:
+ m_pFrame->OnMeasureItem(wParam, lParam);
+ return TRUE; // handled
+ case WM_MOUSELEAVE:
+ OnMouseLeave();
+ break;
+ case WM_MOUSEMOVE:
+ OnMouseMove(wParam, lParam);
+ break;
+ case UWM_POPUPMENU:
+ DoPopupMenu();
+ return 0L;
+ case WM_SYSKEYDOWN:
+ if ((VK_MENU == wParam) || (VK_F10 == wParam))
+ return 0L;
+ break;
+ case WM_SYSKEYUP:
+ if ((VK_MENU == wParam) || (VK_F10 == wParam))
+ {
+ ExitMenu();
+ return 0L;
+ }
+ break;
+ case UWM_GETMENUTHEME:
+ {
+ MenuTheme& tm = GetMenuBarTheme();
+ return (LRESULT)&tm;
+ }
+ case WM_WINDOWPOSCHANGED:
+ OnWindowPosChanged();
+ break;
+ case WM_WINDOWPOSCHANGING:
+ // Bypass CToolBar::WndProcDefault for this message
+ return CWnd::WndProcDefault(uMsg, wParam, lParam);
+
+ } // switch (uMsg)
+
+ return CToolBar::WndProcDefault(uMsg, wParam, lParam);
+ } // LRESULT CMenuBar::WndProcDefault(...)
+
+
+
+ ///////////////////////////////////
+ // Definitions for the CFrame class
+ //
+ inline CFrame::CFrame() : m_tsStatusText(_T("Ready")), m_bShowIndicatorStatus(TRUE), m_bShowMenuStatus(TRUE),
+ m_bUseReBar(FALSE), m_bUseThemes(TRUE), m_bUpdateTheme(FALSE), m_bUseToolBar(TRUE), m_bUseCustomDraw(TRUE),
+ m_bShowStatusBar(TRUE), m_bShowToolBar(TRUE), m_himlMenu(NULL), m_himlMenuDis(NULL),
+ m_AboutDialog(IDW_ABOUT), m_pView(NULL), m_nMaxMRU(0), m_hOldFocus(0), m_nOldID(-1)
+ {
+ ZeroMemory(&m_ThemeMenu, sizeof(m_ThemeMenu));
+
+ // Do either InitCommonControls or InitCommonControlsEx
+ LoadCommonControls();
+
+ // By default, we use the rebar if we can
+ if (GetComCtlVersion() >= 470)
+ m_bUseReBar = TRUE;
+
+ for (int i = 0 ; i < 3 ; ++i)
+ m_OldStatus[i] = _T('\0');
+ }
+
+ inline CFrame::~CFrame()
+ {
+ if (m_himlMenu) ImageList_Destroy(m_himlMenu);
+ if (m_himlMenuDis) ImageList_Destroy(m_himlMenuDis);
+ }
+
+ inline BOOL CFrame::AddMenuIcon(int nID_MenuItem, HICON hIcon, int cx /*= 16*/, int cy /*= 16*/)
+ {
+ // Get ImageList image size
+ int cxOld = 0;
+ int cyOld = 0;
+ ImageList_GetIconSize(m_himlMenu, &cxOld, &cyOld );
+
+ // Create a new ImageList if required
+ if ((cx != cxOld) || (cy != cyOld) || (NULL == m_himlMenu))
+ {
+ if (m_himlMenu) ImageList_Destroy(m_himlMenu);
+ m_himlMenu = ImageList_Create(cx, cy, ILC_COLOR32 | ILC_MASK, 1, 0);
+ m_vMenuIcons.clear();
+ }
+
+ if (ImageList_AddIcon(m_himlMenu, hIcon) != -1)
+ {
+ m_vMenuIcons.push_back(nID_MenuItem);
+
+ // Recreate the Disabled imagelist
+ if (m_himlMenuDis) ImageList_Destroy(m_himlMenuDis);
+ m_himlMenuDis = NULL;
+ m_himlMenuDis = CreateDisabledImageList(m_himlMenu);
+
+ return TRUE;
+ }
+
+ return FALSE;
+ }
+
+ inline UINT CFrame::AddMenuIcons(const std::vector<UINT>& MenuData, COLORREF crMask, UINT ToolBarID, UINT ToolBarDisabledID)
+ // Adds the icons from a bitmap resouce to an internal ImageList for use with popup menu items.
+ // Note: If existing are a different size to the new ones, the old ones will be removed!
+ // The ToolBarDisabledID is ignored unless ToolBarID and ToolBarDisabledID bitmaps are the same size.
+ {
+ // Count the MenuData entries excluding seperators
+ int iImages = 0;
+ for (UINT i = 0 ; i < MenuData.size(); ++i)
+ {
+ if (MenuData[i] != 0) // Don't count seperators
+ {
+ ++iImages;
+ }
+ }
+
+ // Load the button images from Resouce ID
+ CBitmap Bitmap(ToolBarID);
+
+ if ((0 == iImages) || (!Bitmap))
+ return (UINT)m_vMenuIcons.size(); // No valid images, so nothing to do!
+
+ BITMAP bm = Bitmap.GetBitmapData();
+ int iImageWidth = bm.bmWidth / iImages;
+ int iImageHeight = bm.bmHeight;
+
+ // Create the ImageList if required
+ if (NULL == m_himlMenu)
+ {
+ m_himlMenu = ImageList_Create(iImageWidth, iImageHeight, ILC_COLOR32 | ILC_MASK, iImages, 0);
+ m_vMenuIcons.clear();
+ }
+ else
+ {
+ int Oldcx;
+ int Oldcy;
+
+ ImageList_GetIconSize(m_himlMenu, &Oldcx, &Oldcy);
+ if (iImageHeight != Oldcy)
+ {
+ TRACE(_T("Unable to add icons. The new icons are a different size to the old ones\n"));
+ return (UINT)m_vMenuIcons.size();
+ }
+ }
+
+ // Add the resource IDs to the m_vMenuIcons vector
+ for (UINT j = 0 ; j < MenuData.size(); ++j)
+ {
+ if (MenuData[j] != 0)
+ {
+ m_vMenuIcons.push_back(MenuData[j]);
+ }
+ }
+
+ // Add the images to the ImageList
+ ImageList_AddMasked(m_himlMenu, Bitmap, crMask);
+
+ // Create the Disabled imagelist
+ if (ToolBarDisabledID)
+ {
+ if (0 != m_himlMenuDis)
+ m_himlMenuDis = ImageList_Create(iImageWidth, iImageHeight, ILC_COLOR32 | ILC_MASK, iImages, 0);
+
+ CBitmap BitmapDisabled(ToolBarDisabledID);
+ BITMAP bmDis = BitmapDisabled.GetBitmapData();
+
+ int iImageWidthDis = bmDis.bmWidth / iImages;
+ int iImageHeightDis = bmDis.bmHeight;
+
+ // Normal and Disabled icons must be the same size
+ if ((iImageWidthDis == iImageWidth) && (iImageHeightDis == iImageHeight))
+ {
+ ImageList_AddMasked(m_himlMenu, BitmapDisabled, crMask);
+ }
+ else
+ {
+ ImageList_Destroy(m_himlMenuDis);
+ m_himlMenuDis = CreateDisabledImageList(m_himlMenu);
+ }
+ }
+ else
+ {
+ if (m_himlMenuDis) ImageList_Destroy(m_himlMenuDis);
+ m_himlMenuDis = CreateDisabledImageList(m_himlMenu);
+ }
+
+ // return the number of menu icons
+ return (UINT)m_vMenuIcons.size();
+ }
+
+ inline void CFrame::AddMenuBarBand()
+ {
+ // Adds a MenuBar to the rebar control
+ REBARBANDINFO rbbi = {0};
+ CSize sz = GetMenuBar().GetMaxSize();
+
+ // Calculate the MenuBar height from the menu font
+ CSize csMenuBar;
+ CClientDC dcMenuBar(&GetMenuBar());
+ dcMenuBar.SelectObject(GetMenuBar().GetFont());
+ csMenuBar = dcMenuBar.GetTextExtentPoint32(_T("\tSomeText"), lstrlen(_T("\tSomeText")));
+ int MenuBar_Height = csMenuBar.cy + 6;
+
+ rbbi.fMask = RBBIM_CHILDSIZE | RBBIM_STYLE | RBBIM_CHILD | RBBIM_SIZE | RBBIM_ID;
+ rbbi.cxMinChild = sz.cx;
+ rbbi.cx = sz.cx;
+ rbbi.cyMinChild = MenuBar_Height;
+ rbbi.cyMaxChild = MenuBar_Height;
+ rbbi.fStyle = RBBS_BREAK | RBBS_VARIABLEHEIGHT | RBBS_GRIPPERALWAYS ;
+ rbbi.hwndChild = GetMenuBar();
+ rbbi.wID = IDW_MENUBAR;
+
+ // Note: rbbi.cbSize is set inside the InsertBand function
+ GetReBar().InsertBand(-1, rbbi);
+ SetMenuBarBandSize();
+ GetReBar().SetMenuBar(GetMenuBar());
+
+ if (GetReBar().GetReBarTheme().LockMenuBand)
+ GetReBar().ShowGripper(GetReBar().GetBand(GetMenuBar()), FALSE);
+ }
+
+ inline void CFrame::AddMRUEntry(LPCTSTR szMRUEntry)
+ {
+ // Erase possible duplicate entries from vector
+ RemoveMRUEntry(szMRUEntry);
+
+ // Insert the entry at the beginning of the vector
+ m_vMRUEntries.insert(m_vMRUEntries.begin(), szMRUEntry);
+
+ // Delete excessive MRU entries
+ if (m_vMRUEntries.size() > m_nMaxMRU)
+ m_vMRUEntries.erase(m_vMRUEntries.begin() + m_nMaxMRU, m_vMRUEntries.end());
+
+ UpdateMRUMenu();
+ }
+
+ inline void CFrame::AddToolBarBand(CToolBar& TB, DWORD dwStyle, UINT nID)
+ {
+ // Adds a ToolBar to the rebar control
+
+ // Create the ToolBar Window
+ TB.Create(&GetReBar());
+
+ // Fill the REBARBAND structure
+ REBARBANDINFO rbbi = {0};
+ CSize sz = TB.GetMaxSize();
+
+ rbbi.fMask = RBBIM_CHILDSIZE | RBBIM_STYLE | RBBIM_CHILD | RBBIM_SIZE | RBBIM_ID;
+ rbbi.cyMinChild = sz.cy;
+ rbbi.cyMaxChild = sz.cy;
+ rbbi.cx = sz.cx +2;
+ rbbi.cxMinChild = sz.cx +2;
+
+ rbbi.fStyle = dwStyle;
+ rbbi.hwndChild = TB;
+ rbbi.wID = nID;
+
+ // Note: rbbi.cbSize is set inside the InsertBand function
+ GetReBar().InsertBand(-1, rbbi);
+ }
+
+ inline void CFrame::AddToolBarButton(UINT nID, BOOL bEnabled /* = TRUE*/, LPCTSTR szText)
+ // Adds Resource IDs to toolbar buttons.
+ // A resource ID of 0 is a separator
+ {
+ GetToolBar().AddButton(nID, bEnabled);
+
+ if(0 != szText)
+ GetToolBar().SetButtonText(nID, szText);
+
+ if (!IsWindow()) TRACE(_T("Warning ... Resource IDs for toolbars should be added in SetupToolBar\n"));
+ }
+
+ inline void CFrame::AdjustFrameRect(RECT rcView) const
+ // Adjust the size of the frame to accommodate the View window's dimensions
+ {
+ // Adjust for the view styles
+ CRect rc = rcView;
+ DWORD dwStyle = (DWORD)GetView()->GetWindowLongPtr(GWL_STYLE);
+ DWORD dwExStyle = (DWORD)GetView()->GetWindowLongPtr(GWL_EXSTYLE);
+ AdjustWindowRectEx(&rc, dwStyle, FALSE, dwExStyle);
+
+ // Calculate the new frame height
+ CRect rcFrameBefore = GetWindowRect();
+ CRect rcViewBefore = GetViewRect();
+ int Height = rc.Height() + rcFrameBefore.Height() - rcViewBefore.Height();
+
+ // Adjust for the frame styles
+ dwStyle = (DWORD)GetWindowLongPtr(GWL_STYLE);
+ dwExStyle = (DWORD)GetWindowLongPtr(GWL_EXSTYLE);
+ AdjustWindowRectEx(&rc, dwStyle, FALSE, dwExStyle);
+
+ // Calculate final rect size, and reposition frame
+ SetWindowPos(NULL, 0, 0, rc.Width(), Height, SWP_NOMOVE);
+ }
+
+ inline void CFrame::CreateToolBar()
+ {
+ if (IsReBarSupported() && m_bUseReBar)
+ AddToolBarBand(GetToolBar(), RBBS_BREAK, IDW_TOOLBAR); // Create the toolbar inside rebar
+ else
+ GetToolBar().Create(this); // Create the toolbar without a rebar
+
+ SetupToolBar();
+
+ if (IsReBarSupported() && m_bUseReBar)
+ {
+ if (GetReBar().GetReBarTheme().UseThemes && GetReBar().GetReBarTheme().LockMenuBand)
+ {
+ // Hide gripper for single toolbar
+ if (GetReBar().GetBandCount() <= 2)
+ GetReBar().ShowGripper(GetReBar().GetBand(GetToolBar()), FALSE);
+ }
+ }
+
+ if (GetToolBar().GetToolBarData().size() > 0)
+ {
+ // Set the toolbar images (if not already set in SetupToolBar)
+ // A mask of 192,192,192 is compatible with AddBitmap (for Win95)
+ if (!GetToolBar().SendMessage(TB_GETIMAGELIST, 0L, 0L))
+ SetToolBarImages(RGB(192,192,192), IDW_MAIN, 0, 0);
+
+ // Add the icons for popup menu
+ AddMenuIcons(GetToolBar().GetToolBarData(), RGB(192, 192, 192), IDW_MAIN, 0);
+ }
+ else
+ {
+ TRACE(_T("Warning ... No resource IDs assigned to the toolbar\n"));
+ }
+ }
+
+ inline void CFrame::DrawCheckmark(LPDRAWITEMSTRUCT pdis, CDC& DrawDC)
+ // Draws the checkmark or radiocheck transparently
+ {
+ CRect rc = pdis->rcItem;
+ UINT fType = ((ItemData*)pdis->itemData)->fType;
+ MenuTheme tm = GetMenuTheme();
+ CRect rcBk;
+
+ // Draw the checkmark's background rectangle first
+ int Iconx = 16, Icony = 16;
+ if (m_himlMenu) ImageList_GetIconSize(m_himlMenu, &Iconx, &Icony);
+ int BarWidth = Iconx + 8;
+ int left = (BarWidth - Iconx)/2;
+ int top = rc.top + (rc.Height() - Icony)/2;
+ rcBk.SetRect(left, top, left + Iconx, top + Icony);
+
+ if (tm.UseThemes)
+ {
+ DrawDC.CreateSolidBrush(tm.clrHot2);
+ DrawDC.CreatePen(PS_SOLID, 1, tm.clrOutline);
+
+ // Draw the checkmark's background rectangle
+ DrawDC.Rectangle(rcBk.left, rcBk.top, rcBk.right, rcBk.bottom);
+ }
+
+ CMemDC MemDC(FromHandle(pdis->hDC));
+ int cxCheck = ::GetSystemMetrics(SM_CXMENUCHECK);
+ int cyCheck = ::GetSystemMetrics(SM_CYMENUCHECK);
+ MemDC.CreateBitmap(cxCheck, cyCheck, 1, 1, NULL);
+ CRect rcCheck( 0, 0, cxCheck, cyCheck);
+
+ // Copy the check mark bitmap to hdcMem
+ if (MFT_RADIOCHECK == fType)
+ MemDC.DrawFrameControl(rcCheck, DFC_MENU, DFCS_MENUBULLET);
+ else
+ MemDC.DrawFrameControl(rcCheck, DFC_MENU, DFCS_MENUCHECK);
+
+ int xoffset = (rcBk.Width() - rcCheck.Width()-1)/2;
+ int yoffset = (rcBk.Height() - rcCheck.Height()-1)/2;
+
+ if (tm.UseThemes)
+ xoffset += 2;
+
+ // Draw a white or black check mark as required
+ // Unfortunately MaskBlt isn't supported on Win95, 98 or ME, so we do it the hard way
+ CMemDC MaskDC(FromHandle(pdis->hDC));
+ MaskDC.CreateCompatibleBitmap(FromHandle(pdis->hDC), cxCheck, cyCheck);
+ MaskDC.BitBlt(0, 0, cxCheck, cyCheck, &MaskDC, 0, 0, WHITENESS);
+
+ if ((pdis->itemState & ODS_SELECTED) && (!tm.UseThemes))
+ {
+ // Draw a white checkmark
+ MemDC.BitBlt(0, 0, cxCheck, cyCheck, &MemDC, 0, 0, DSTINVERT);
+ MaskDC.BitBlt(0, 0, cxCheck, cyCheck, &MemDC, 0, 0, SRCAND);
+ DrawDC.BitBlt(rcBk.left + xoffset, rcBk.top + yoffset, cxCheck, cyCheck, &MaskDC, 0, 0, SRCPAINT);
+ }
+ else
+ {
+ // Draw a black checkmark
+ int BullitOffset = ((MFT_RADIOCHECK == fType) && tm.UseThemes)? 1 : 0;
+ MaskDC.BitBlt( -BullitOffset, BullitOffset, cxCheck, cyCheck, &MemDC, 0, 0, SRCAND);
+ DrawDC.BitBlt(rcBk.left + xoffset, rcBk.top + yoffset, cxCheck, cyCheck, &MaskDC, 0, 0, SRCAND);
+ }
+ }
+
+ inline void CFrame::DrawMenuIcon(LPDRAWITEMSTRUCT pdis, CDC& DrawDC, BOOL bDisabled)
+ {
+ if (!m_himlMenu)
+ return;
+ // Get icon size
+ int Iconx;
+ int Icony;
+ ImageList_GetIconSize(m_himlMenu, &Iconx, &Icony);
+ int BarWidth = Iconx + 8;
+
+ // get the drawing rectangle
+ CRect rc = pdis->rcItem;
+ int left = (BarWidth - Iconx)/2;
+ int top = rc.top + (rc.Height() - Icony)/2;
+ rc.SetRect(left, top, left + Iconx, top + Icony);
+
+ // get the icon's location in the imagelist
+ int iImage = -1;
+ for (int i = 0 ; i < (int)m_vMenuIcons.size(); ++i)
+ {
+ if (pdis->itemID == m_vMenuIcons[i])
+ iImage = i;
+ }
+
+ // draw the image
+ if (iImage >= 0 )
+ {
+ if ((bDisabled) && (m_himlMenuDis))
+ ImageList_Draw(m_himlMenuDis, iImage, DrawDC, rc.left, rc.top, ILD_TRANSPARENT);
+ else
+ ImageList_Draw(m_himlMenu, iImage, DrawDC, rc.left, rc.top, ILD_TRANSPARENT);
+ }
+ }
+
+ inline void CFrame::DrawMenuText(CDC& DrawDC, LPCTSTR ItemText, CRect& rc, COLORREF colorText)
+ {
+ // find the position of tab character
+ int nTab = -1;
+ for(int i = 0; i < lstrlen(ItemText); ++i)
+ {
+ if(_T('\t') == ItemText[i])
+ {
+ nTab = i;
+ break;
+ }
+ }
+
+ // Draw the item text
+ DrawDC.SetTextColor(colorText);
+ DrawDC.DrawText(ItemText, nTab, rc, DT_SINGLELINE | DT_LEFT | DT_VCENTER);
+
+ // Draw text after tab, right aligned
+ if(nTab != -1)
+ DrawDC.DrawText( &ItemText[nTab + 1], -1, rc, DT_SINGLELINE | DT_RIGHT | DT_VCENTER);
+ }
+
+ inline int CFrame::GetMenuItemPos(HMENU hMenu, LPCTSTR szItem)
+ // Returns the position of the menu item, given it's name
+ {
+ int nMenuItemCount = GetMenuItemCount(hMenu);
+ MENUITEMINFO mii = {0};
+ mii.cbSize = GetSizeofMenuItemInfo();
+
+ for (int nItem = 0 ; nItem < nMenuItemCount; ++nItem)
+ {
+ std::vector<TCHAR> vTChar( MAX_MENU_STRING+1, _T('\0') );
+ TCHAR* szStr = &vTChar[0];
+
+ std::vector<TCHAR> vStripped( MAX_MENU_STRING+1, _T('\0') );
+ TCHAR* szStripped = &vStripped[0];
+
+ mii.fMask = MIIM_TYPE;
+ mii.fType = MFT_STRING;
+ mii.dwTypeData = szStr;
+ mii.cch = MAX_MENU_STRING;
+
+ // Fill the contents of szStr from the menu item
+ if (::GetMenuItemInfo(hMenu, nItem, TRUE, &mii) && (lstrlen(szStr) <= MAX_MENU_STRING))
+ {
+ // Strip out any & characters
+ int j = 0;
+ for (int i = 0; i < lstrlen(szStr); ++i)
+ {
+ if (szStr[i] != _T('&'))
+ szStripped[j++] = szStr[i];
+ }
+ szStripped[j] = _T('\0'); // Append null tchar
+
+ // Compare the strings
+ if (0 == lstrcmp(szStripped, szItem))
+ return nItem;
+ }
+ }
+
+ return -1;
+ }
+
+ inline tString CFrame::GetMRUEntry(UINT nIndex)
+ {
+ tString tsPathName;
+ if (nIndex < m_vMRUEntries.size())
+ {
+ tsPathName = m_vMRUEntries[nIndex];
+
+ // Now put the selected entry at Index 0
+ AddMRUEntry(tsPathName.c_str());
+ }
+ return tsPathName;
+ }
+
+ inline CRect CFrame::GetViewRect() const
+ {
+ // Get the frame's client area
+ CRect rcFrame = GetClientRect();
+
+ // Get the statusbar's window area
+ CRect rcStatus;
+ if (GetStatusBar().IsWindowVisible() || !IsWindowVisible())
+ rcStatus = GetStatusBar().GetWindowRect();
+
+ // Get the top rebar or toolbar's window area
+ CRect rcTop;
+ if (IsReBarSupported() && m_bUseReBar)
+ rcTop = GetReBar().GetWindowRect();
+ else
+ if (GetToolBar().IsWindow() && GetToolBar().IsWindowVisible())
+ rcTop = GetToolBar().GetWindowRect();
+
+ // Return client size less the rebar and status windows
+ int top = rcFrame.top + rcTop.Height();
+ int left = rcFrame.left;
+ int right = rcFrame.right;
+ int bottom = rcFrame.Height() - (rcStatus.Height());
+ if ((bottom <= top) ||( right <= left))
+ top = left = right = bottom = 0;
+
+ CRect rcView(left, top, right, bottom);
+ return rcView;
+ }
+
+ inline void CFrame::LoadCommonControls()
+ {
+ HMODULE hComCtl;
+
+ try
+ {
+ // Load the Common Controls DLL
+ hComCtl = ::LoadLibrary(_T("COMCTL32.DLL"));
+ if (!hComCtl)
+ throw CWinException(_T("Failed to load COMCTL32.DLL"));
+
+ if (GetComCtlVersion() > 470)
+ {
+ // Declare a pointer to the InItCommonControlsEx function
+ typedef BOOL WINAPI INIT_EX(INITCOMMONCONTROLSEX*);
+ INIT_EX* pfnInit = (INIT_EX*)::GetProcAddress(hComCtl, "InitCommonControlsEx");
+
+ // Load the full set of common controls
+ INITCOMMONCONTROLSEX InitStruct = {0};
+ InitStruct.dwSize = sizeof(INITCOMMONCONTROLSEX);
+ InitStruct.dwICC = ICC_COOL_CLASSES|ICC_DATE_CLASSES|ICC_INTERNET_CLASSES|ICC_NATIVEFNTCTL_CLASS|
+ ICC_PAGESCROLLER_CLASS|ICC_USEREX_CLASSES|ICC_WIN95_CLASSES;
+
+ // Call InitCommonControlsEx
+ if(!((*pfnInit)(&InitStruct)))
+ throw CWinException(_T("InitCommonControlsEx failed"));
+ }
+ else
+ {
+ ::InitCommonControls();
+ }
+
+ ::FreeLibrary(hComCtl);
+ }
+
+ catch (const CWinException &e)
+ {
+ e.what();
+ if (hComCtl)
+ ::FreeLibrary(hComCtl);
+
+ throw;
+ }
+ }
+
+ inline BOOL CFrame::LoadRegistryMRUSettings(UINT nMaxMRU /*= 0*/)
+ {
+ // Load the MRU list from the registry
+
+ assert(!m_tsKeyName.empty()); // KeyName must be set before calling LoadRegistryMRUSettings
+ HKEY hKey = NULL;
+ BOOL bRet = FALSE;
+
+ try
+ {
+ m_nMaxMRU = MIN(nMaxMRU, 16);
+ std::vector<tString> vMRUEntries;
+ tString tsKey = _T("Software\\") + m_tsKeyName + _T("\\Recent Files");
+
+ if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER, tsKey.c_str(), 0, KEY_READ, &hKey))
+ {
+ for (UINT i = 0; i < m_nMaxMRU; ++i)
+ {
+ DWORD dwType = REG_SZ;
+ DWORD dwBufferSize = 0;
+ TCHAR szSubKey[10] = _T("");
+ wsprintf(szSubKey, _T("File %d\0"), i+1);
+
+ if (ERROR_SUCCESS != RegQueryValueEx(hKey, szSubKey, NULL, &dwType, NULL, &dwBufferSize))
+ throw CWinException(_T("RegQueryValueEx failed\n"));
+
+ std::vector<TCHAR> PathName( dwBufferSize, _T('\0') );
+ TCHAR* pTCharArray = &PathName[0];
+
+ // load the entry from the registry
+ if (ERROR_SUCCESS != RegQueryValueEx(hKey, szSubKey, NULL, &dwType, (LPBYTE)pTCharArray, &dwBufferSize))
+ throw CWinException(_T("RegQueryValueEx failed\n"));
+
+ if ( lstrlen( pTCharArray ) )
+ vMRUEntries.push_back( pTCharArray );
+ }
+
+ // successfully loaded all MRU values, so store them
+ m_vMRUEntries = vMRUEntries;
+ RegCloseKey(hKey);
+ bRet = TRUE;
+ }
+ }
+
+ catch(const CWinException& e)
+ {
+ TRACE(_T("Failed to load MRU values from registry\n"));
+ e.what();
+
+ if (hKey)
+ RegCloseKey(hKey);
+ }
+
+ return bRet;
+ }
+
+ inline BOOL CFrame::LoadRegistrySettings(LPCTSTR szKeyName)
+ {
+ assert (NULL != szKeyName);
+ m_tsKeyName = szKeyName;
+
+ tString tsKey = _T("Software\\") + m_tsKeyName + _T("\\Frame Settings");
+ HKEY hKey = 0;
+ BOOL bRet = FALSE;
+
+ try
+ {
+ if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER, tsKey.c_str(), 0, KEY_READ, &hKey))
+ {
+ DWORD dwType = REG_BINARY;
+ DWORD BufferSize = sizeof(DWORD);
+ DWORD dwTop, dwLeft, dwWidth, dwHeight, dwStatusBar, dwToolBar;
+ if (ERROR_SUCCESS != RegQueryValueEx(hKey, _T("Top"), NULL, &dwType, (LPBYTE)&dwTop, &BufferSize))
+ throw CWinException(_T("RegQueryValueEx Failed"));
+ if (ERROR_SUCCESS != RegQueryValueEx(hKey, _T("Left"), NULL, &dwType, (LPBYTE)&dwLeft, &BufferSize))
+ throw CWinException(_T("RegQueryValueEx Failed"));
+ if (ERROR_SUCCESS != RegQueryValueEx(hKey, _T("Width"), NULL, &dwType, (LPBYTE)&dwWidth, &BufferSize))
+ throw CWinException(_T("RegQueryValueEx Failed"));
+ if (ERROR_SUCCESS != RegQueryValueEx(hKey, _T("Height"), NULL, &dwType, (LPBYTE)&dwHeight, &BufferSize))
+ throw CWinException(_T("RegQueryValueEx Failed"));
+ if (ERROR_SUCCESS != RegQueryValueEx(hKey, _T("StatusBar"), NULL, &dwType, (LPBYTE)&dwStatusBar, &BufferSize))
+ throw CWinException(_T("RegQueryValueEx Failed"));
+ if (ERROR_SUCCESS != RegQueryValueEx(hKey, _T("ToolBar"), NULL, &dwType, (LPBYTE)&dwToolBar, &BufferSize))
+ throw CWinException(_T("RegQueryValueEx Failed"));
+
+ m_rcPosition.top = dwTop;
+ m_rcPosition.left = dwLeft;
+ m_rcPosition.bottom = m_rcPosition.top + dwHeight;
+ m_rcPosition.right = m_rcPosition.left + dwWidth;
+ m_bShowStatusBar = dwStatusBar & 1;
+ m_bShowToolBar = dwToolBar & 1;
+
+ RegCloseKey(hKey);
+ bRet = TRUE;
+ }
+ }
+
+ catch (const CWinException& e)
+ {
+ TRACE(_T("Failed to load values from registry, using defaults!\n"));
+ e.what();
+
+ if (hKey)
+ RegCloseKey(hKey);
+ }
+
+ return bRet;
+ }
+
+ inline void CFrame::OnActivate(WPARAM wParam, LPARAM lParam)
+ {
+ // Do default processing first
+ DefWindowProc(WM_ACTIVATE, wParam, lParam);
+
+ if (LOWORD(wParam) == WA_INACTIVE)
+ {
+ // Save the hwnd of the window which currently has focus
+ // (this must be CFrame window itself or a child window
+ if (!IsIconic()) m_hOldFocus = ::GetFocus();
+
+ // Send a notification to the view window
+ int idCtrl = ::GetDlgCtrlID(m_hOldFocus);
+ NMHDR nhdr={0};
+ nhdr.hwndFrom = m_hOldFocus;
+ nhdr.idFrom = idCtrl;
+ nhdr.code = UWM_FRAMELOSTFOCUS;
+ if (GetView()->IsWindow())
+ GetView()->SendMessage(WM_NOTIFY, (WPARAM)idCtrl, (LPARAM)&nhdr);
+ }
+ else
+ {
+ // Now set the focus to the appropriate child window
+ if (m_hOldFocus) ::SetFocus(m_hOldFocus);
+
+ // Send a notification to the view window
+ int idCtrl = ::GetDlgCtrlID(m_hOldFocus);
+ NMHDR nhdr={0};
+ nhdr.hwndFrom = m_hOldFocus;
+ nhdr.idFrom = idCtrl;
+ nhdr.code = UWM_FRAMEGOTFOCUS;
+ if (GetView()->IsWindow())
+ GetView()->SendMessage(WM_NOTIFY, (WPARAM)idCtrl, (LPARAM)&nhdr);
+ }
+ }
+
+ inline void CFrame::OnClose()
+ {
+ // Called in response to a WM_CLOSE message for the frame.
+ ShowWindow(SW_HIDE);
+ SaveRegistrySettings();
+
+ GetMenuBar().Destroy();
+ GetToolBar().Destroy();
+ GetReBar().Destroy();
+ GetStatusBar().Destroy();
+ GetView()->Destroy();
+ }
+
+ inline void CFrame::OnCreate()
+ {
+ // This is called when the frame window is being created.
+ // Override this in CMainFrame if you wish to modify what happens here
+
+ // Set the icon
+ SetIconLarge(IDW_MAIN);
+ SetIconSmall(IDW_MAIN);
+
+ // Set the keyboard accelerators
+ m_hAccel = LoadAccelerators(GetApp()->GetResourceHandle(), MAKEINTRESOURCE(IDW_MAIN));
+ GetApp()->SetAccelerators(m_hAccel, this);
+
+ // Set the Caption
+ SetWindowText(LoadString(IDW_MAIN));
+
+ // Set the theme for the frame elements
+ SetTheme();
+
+ // Create the rebar and menubar
+ if (IsReBarSupported() && m_bUseReBar)
+ {
+ // Create the rebar
+ GetReBar().Create(this);
+
+ // Create the menu inside rebar
+ GetMenuBar().Create(&GetReBar());
+ AddMenuBarBand();
+ }
+
+ // Setup the menu
+ SetFrameMenu(IDW_MAIN);
+ UpdateMRUMenu();
+
+ // Create the ToolBar
+ if (m_bUseToolBar)
+ {
+ CreateToolBar();
+ ShowToolBar(m_bShowToolBar);
+ }
+ else
+ {
+ ::CheckMenuItem(GetFrameMenu(), IDW_VIEW_TOOLBAR, MF_UNCHECKED);
+ ::EnableMenuItem(GetFrameMenu(), IDW_VIEW_TOOLBAR, MF_GRAYED);
+ }
+
+ // Create the status bar
+ GetStatusBar().Create(this);
+ ShowStatusBar(m_bShowStatusBar);
+
+ // Create the view window
+ assert(GetView()); // Use SetView in CMainFrame's constructor to set the view window
+ GetView()->Create(this);
+
+ // Disable XP themes for the menubar
+ if ( m_bUseThemes || (GetWinVersion() < 2600) ) // themes or WinVersion < Vista
+ GetMenuBar().SetWindowTheme(L" ", L" ");
+
+ // Start timer for Status updates
+ if (m_bShowIndicatorStatus || m_bShowMenuStatus)
+ SetTimer(ID_STATUS_TIMER, 200, NULL);
+
+ // Reposition the child windows
+ RecalcLayout();
+ }
+
+ inline void CFrame::OnDestroy()
+ {
+ SetMenu(NULL);
+ KillTimer(ID_STATUS_TIMER);
+ ::PostQuitMessage(0); // Terminates the application
+ }
+
+ inline LRESULT CFrame::OnDrawItem(WPARAM wParam, LPARAM lParam)
+ // OwnerDraw is used to render the popup menu items
+ {
+ LPDRAWITEMSTRUCT pdis = (LPDRAWITEMSTRUCT) lParam;
+ if (pdis->CtlType != ODT_MENU)
+ return CWnd::WndProcDefault(WM_DRAWITEM, wParam, lParam);
+
+ CRect rc = pdis->rcItem;
+ ItemData* pmd = (ItemData*)pdis->itemData;
+ CDC* pDrawDC = FromHandle(pdis->hDC);
+ MenuTheme tm = GetMenuTheme();
+
+ int Iconx = 16;
+ int Icony = 16;
+ if (m_himlMenu) ImageList_GetIconSize(m_himlMenu, &Iconx, &Icony);
+ int BarWidth = tm.UseThemes? Iconx + 8 : 0;
+
+ // Draw the side bar
+ if (tm.UseThemes)
+ {
+ CRect rcBar = rc;
+ rcBar.right = BarWidth;
+ pDrawDC->GradientFill(tm.clrPressed1, tm.clrPressed2, rcBar, TRUE);
+ }
+
+ if (pmd->fType & MFT_SEPARATOR)
+ {
+ // draw separator
+ CRect rcSep = rc;
+ rcSep.left = BarWidth;
+ if (tm.UseThemes)
+ pDrawDC->SolidFill(RGB(255,255,255), rcSep);
+ else
+ pDrawDC->SolidFill(GetSysColor(COLOR_MENU), rcSep);
+ rcSep.top += (rc.bottom - rc.top)/2;
+ rcSep.left = BarWidth + 2;
+ pDrawDC->DrawEdge(rcSep, EDGE_ETCHED, BF_TOP);
+ }
+ else
+ {
+ // draw menu item
+ BOOL bDisabled = pdis->itemState & ODS_GRAYED;
+ BOOL bSelected = pdis->itemState & ODS_SELECTED;
+ BOOL bChecked = pdis->itemState & ODS_CHECKED;
+ CRect rcDraw = rc;
+
+ if ((bSelected) && (!bDisabled))
+ {
+ // draw selected item background
+ if (tm.UseThemes)
+ {
+ pDrawDC->CreateSolidBrush(tm.clrHot1);
+ pDrawDC->CreatePen(PS_SOLID, 1, tm.clrOutline);
+ pDrawDC->Rectangle(rcDraw.left, rcDraw.top, rcDraw.right, rcDraw.bottom);
+ }
+ else
+ pDrawDC->SolidFill(GetSysColor(COLOR_HIGHLIGHT), rcDraw);
+ }
+ else
+ {
+ // draw non-selected item background
+ rcDraw.left = BarWidth;
+ if (tm.UseThemes)
+ pDrawDC->SolidFill(RGB(255,255,255), rcDraw);
+ else
+ pDrawDC->SolidFill(GetSysColor(COLOR_MENU), rcDraw);
+ }
+
+ if (bChecked)
+ DrawCheckmark(pdis, *pDrawDC);
+ else
+ DrawMenuIcon(pdis, *pDrawDC, bDisabled);
+
+ // Calculate the text rect size
+ rc.left = rc.bottom - rc.top + 2;
+ if (_tcschr(pmd->GetItemText(), _T('\t')))
+ rc.right -= POST_TEXT_GAP; // Add POST_TEXT_GAP if the text includes a tab
+
+ // Draw the text
+ int iMode = pDrawDC->SetBkMode(TRANSPARENT);
+ COLORREF colorText;
+ if (tm.UseThemes)
+ {
+ rc.left += 8;
+ colorText = GetSysColor(bDisabled ? COLOR_GRAYTEXT : COLOR_MENUTEXT);
+ }
+ else
+ colorText = GetSysColor(bDisabled ? COLOR_GRAYTEXT : bSelected ? COLOR_HIGHLIGHTTEXT : COLOR_MENUTEXT);
+
+ DrawMenuText(*pDrawDC, pmd->GetItemText(), rc, colorText);
+ pDrawDC->SetBkMode(iMode);
+ }
+
+ pDrawDC->Detach(); // Optional, deletes GDI objects sooner
+ return TRUE;
+ }
+
+ inline void CFrame::OnExitMenuLoop()
+ {
+ if (m_bUseCustomDraw)
+ {
+ for (UINT nItem = 0; nItem < m_vMenuItemData.size(); ++nItem)
+ {
+ // Undo OwnerDraw and put the text back
+ MENUITEMINFO mii = {0};
+ mii.cbSize = GetSizeofMenuItemInfo();
+
+ mii.fMask = MIIM_TYPE | MIIM_DATA;
+ mii.fType = m_vMenuItemData[nItem]->fType;
+ mii.dwTypeData = m_vMenuItemData[nItem]->GetItemText();
+ mii.cch = lstrlen(m_vMenuItemData[nItem]->GetItemText());
+ mii.dwItemData = 0;
+ ::SetMenuItemInfo(m_vMenuItemData[nItem]->hMenu, m_vMenuItemData[nItem]->nPos, TRUE, &mii);
+ }
+
+ m_vMenuItemData.clear();
+ }
+ }
+
+ inline void CFrame::OnHelp()
+ {
+ // Ensure only one dialog displayed even for multiple hits of the F1 button
+ if (!m_AboutDialog.IsWindow())
+ {
+ // Store the window handle that currently has keyboard focus
+ HWND hPrevFocus = ::GetFocus();
+ if (hPrevFocus == GetMenuBar())
+ hPrevFocus = m_hWnd;
+
+ m_AboutDialog.SetDlgParent(this);
+ m_AboutDialog.DoModal();
+
+ ::SetFocus(hPrevFocus);
+ }
+ }
+
+ inline void CFrame::OnInitMenuPopup(WPARAM wParam, LPARAM lParam)
+ {
+ // The system menu shouldn't be owner drawn
+ if (HIWORD(lParam)) return;
+
+ if (m_bUseCustomDraw)
+ {
+ CMenu* pMenu = FromHandle((HMENU)wParam);
+
+ for (UINT i = 0; i < pMenu->GetMenuItemCount(); ++i)
+ {
+ MENUITEMINFO mii = {0};
+ mii.cbSize = GetSizeofMenuItemInfo();
+
+ TCHAR szMenuItem[MAX_MENU_STRING] = _T("");
+
+ // Use old fashioned MIIM_TYPE instead of MIIM_FTYPE for MS VC6 compatibility
+ mii.fMask = MIIM_TYPE | MIIM_DATA | MIIM_SUBMENU;
+ mii.dwTypeData = szMenuItem;
+ mii.cch = MAX_MENU_STRING -1;
+
+ // Send message for menu updates
+ UINT menuItem = pMenu->GetMenuItemID(i);
+ SendMessage(UWM_UPDATE_COMMAND, (WPARAM)menuItem, 0);
+
+ // Specify owner-draw for the menu item type
+ if (pMenu->GetMenuItemInfo(i, &mii, TRUE))
+ {
+ if (0 == mii.dwItemData)
+ {
+ ItemData* pItem = new ItemData; // deleted in OnExitMenuLoop
+ pItem->hMenu = *pMenu;
+ pItem->nPos = i;
+ pItem->fType = mii.fType;
+ pItem->hSubMenu = mii.hSubMenu;
+ mii.fType |= MFT_OWNERDRAW;
+ lstrcpyn(pItem->GetItemText(), szMenuItem, MAX_MENU_STRING);
+ mii.dwItemData = (DWORD_PTR)pItem;
+
+ m_vMenuItemData.push_back(ItemDataPtr(pItem)); // Store pItem in m_vMenuItemData
+ pMenu->SetMenuItemInfo(i, &mii, TRUE); // Store pItem in mii
+ }
+ }
+ }
+ }
+ }
+
+ inline LRESULT CFrame::OnMeasureItem(WPARAM wParam, LPARAM lParam)
+ // Called before the Popup menu is displayed, so that the MEASUREITEMSTRUCT
+ // values can be assigned with the menu item's dimensions.
+ {
+ LPMEASUREITEMSTRUCT pmis = (LPMEASUREITEMSTRUCT) lParam;
+ if (pmis->CtlType != ODT_MENU)
+ return CWnd::WndProcDefault(WM_MEASUREITEM, wParam, lParam);
+
+ ItemData* pmd = (ItemData *) pmis->itemData;
+ assert(::IsMenu(pmd->hMenu)); // Does itemData contain a valid ItemData struct?
+ MenuTheme tm = GetMenuTheme();
+
+ if (pmd->fType & MFT_SEPARATOR)
+ {
+ pmis->itemHeight = 7;
+ pmis->itemWidth = 0;
+ }
+
+ else
+ {
+ CClientDC DesktopDC(NULL);
+
+ // Get the font used in menu items
+ NONCLIENTMETRICS nm = {0};
+ nm.cbSize = GetSizeofNonClientMetrics();
+ SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(nm), &nm, 0);
+ // Default menu items are bold, so take this into account
+ if ((int)::GetMenuDefaultItem(pmd->hMenu, TRUE, GMDI_USEDISABLED) != -1)
+ nm.lfMenuFont.lfWeight = FW_BOLD;
+
+ TCHAR* pItemText = &(pmd->vItemText[0]);
+ DesktopDC.CreateFontIndirect(&nm.lfMenuFont);
+
+ // Calculate the size of the text
+ CSize size = DesktopDC.GetTextExtentPoint32(pItemText, lstrlen(pItemText));
+
+ // Calculate the size of the icon
+ int Iconx = 16;
+ int Icony = 16;
+ if (m_himlMenu) ImageList_GetIconSize(m_himlMenu, &Iconx, &Icony);
+
+ pmis->itemHeight = 2+ MAX(MAX(size.cy, GetSystemMetrics(SM_CYMENU)-2), Icony+2);
+ pmis->itemWidth = size.cx + MAX(::GetSystemMetrics(SM_CXMENUSIZE), Iconx+2);
+
+ // Allow extra width if the text includes a tab
+ if (_tcschr(pItemText, _T('\t')))
+ pmis->itemWidth += POST_TEXT_GAP;
+
+ // Allow extra width if the menu item has a sub menu
+ if (pmd->hSubMenu)
+ pmis->itemWidth += 10;
+
+ // Allow extra width for themed menu
+ if (tm.UseThemes)
+ pmis->itemWidth += 8;
+ }
+ return TRUE;
+ }
+
+ inline LRESULT CFrame::OnMenuChar(WPARAM wParam, LPARAM lParam)
+ {
+ if ((IsMenuBarUsed()) && (LOWORD(wParam)!= VK_SPACE))
+ {
+ // Activate MenuBar for key pressed with Alt key held down
+ GetMenuBar().OnMenuChar(wParam, lParam);
+ return -1L;
+ }
+ return CWnd::WndProcDefault(WM_MENUCHAR, wParam, lParam);
+ }
+
+ inline void CFrame::OnMenuSelect(WPARAM wParam, LPARAM lParam)
+ {
+ // Set the StatusBar text when we hover over a menu
+ // Only popup submenus have status strings
+ if (m_bShowMenuStatus)
+ {
+ int nID = LOWORD (wParam);
+ CMenu* pMenu = FromHandle((HMENU) lParam);
+
+ if ((pMenu != GetMenu()) && (nID != 0) && !(HIWORD(wParam) & MF_POPUP))
+ m_tsStatusText = LoadString(nID);
+ else
+ m_tsStatusText = _T("Ready");
+
+ SetStatusText();
+ }
+ }
+
+ inline LRESULT CFrame::OnNotify(WPARAM wParam, LPARAM lParam)
+ {
+ UNREFERENCED_PARAMETER(wParam);
+
+ switch (((LPNMHDR)lParam)->code)
+ {
+ case UWM_UNDOCKED:
+ m_hOldFocus = 0;
+ break;
+ case RBN_HEIGHTCHANGE:
+ RecalcLayout();
+ Invalidate();
+ break;
+ // case RBN_LAYOUTCHANGED:
+ // if (GetReBar().GetReBarTheme().UseThemes && GetReBar().GetReBarTheme().BandsLeft)
+ // GetReBar().MoveBandsLeft();
+ // break;
+ case RBN_MINMAX:
+ if (GetReBar().GetReBarTheme().UseThemes && GetReBar().GetReBarTheme().ShortBands)
+ return 1L; // Supress maximise or minimise rebar band
+ break;
+
+ // Display tooltips for the toolbar
+ case TTN_GETDISPINFO:
+ if (GetToolBar().IsWindow())
+ {
+ CToolBar* pToolBar = 0;
+ if (IsReBarUsed())
+ {
+ // Get the ToolBar's CWnd
+ CWnd* pWnd = FromHandle(GetReBar().HitTest(GetCursorPos()));
+ if (pWnd && (lstrcmp(pWnd->GetClassName(), _T("ToolbarWindow32")) == 0))
+ {
+ pToolBar = (CToolBar*)pWnd;
+ }
+ }
+
+ if (pToolBar)
+ {
+ LPNMTTDISPINFO lpDispInfo = (LPNMTTDISPINFO)lParam;
+ int iIndex = pToolBar->HitTest();
+ if (iIndex >= 0)
+ {
+ int nID = pToolBar->GetCommandID(iIndex);
+ if (nID > 0)
+ {
+ m_tsTooltip = LoadString(nID);
+ lpDispInfo->lpszText = (LPTSTR)m_tsTooltip.c_str();
+ }
+ else
+ m_tsTooltip = _T("");
+ }
+ }
+ }
+ break;
+ } // switch LPNMHDR
+
+ return 0L;
+
+ } // CFrame::Onotify(...)
+
+ inline void CFrame::OnSetFocus()
+ {
+ SetStatusText();
+ }
+
+ inline void CFrame::OnSysColorChange()
+ {
+ // Honour theme color changes
+ for (int nBand = 0; nBand <= GetReBar().GetBandCount(); ++nBand)
+ {
+ GetReBar().SetBandColor(nBand, GetSysColor(COLOR_BTNTEXT), GetSysColor(COLOR_BTNFACE));
+ }
+
+ // Update the status bar font and text
+ NONCLIENTMETRICS nm = {0};
+ nm.cbSize = GetSizeofNonClientMetrics();
+ SystemParametersInfo (SPI_GETNONCLIENTMETRICS, 0, &nm, 0);
+ LOGFONT lf = nm.lfStatusFont;
+ CFont* pFont = FromHandle(CreateFontIndirect(&lf));
+ GetStatusBar().SetFont(pFont, FALSE);
+ SetStatusText();
+
+ if ((m_bUpdateTheme) && (m_bUseThemes)) SetTheme();
+
+ // Reposition and redraw everything
+ RecalcLayout();
+ RedrawWindow(NULL, NULL, RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN);
+
+ // Forward the message to the view window
+ m_pView->PostMessage(WM_SYSCOLORCHANGE, 0L, 0L);
+ }
+
+ inline LRESULT CFrame::OnSysCommand(WPARAM wParam, LPARAM lParam)
+ {
+ if ((SC_KEYMENU == wParam) && (VK_SPACE != lParam) && IsMenuBarUsed())
+ {
+ GetMenuBar().OnSysCommand(wParam, lParam);
+ return 0L;
+ }
+
+ if (SC_MINIMIZE == wParam)
+ m_hOldFocus = ::GetFocus();
+
+ return CWnd::WndProcDefault(WM_SYSCOMMAND, wParam, lParam);
+ }
+
+ inline void CFrame::OnTimer(WPARAM wParam)
+ {
+ if (ID_STATUS_TIMER == wParam)
+ {
+ if (m_bShowMenuStatus)
+ {
+ // Get the toolbar the point is over
+ CToolBar* pToolBar = 0;
+ if (IsReBarUsed())
+ {
+ // Get the ToolBar's CWnd
+ CWnd* pWnd = FromHandle(GetReBar().HitTest(GetCursorPos()));
+ if (pWnd && (dynamic_cast<CToolBar*>(pWnd)) && !(dynamic_cast<CMenuBar*>(pWnd)))
+ pToolBar = (CToolBar*)pWnd;
+ }
+ else
+ {
+ CPoint pt = GetCursorPos();
+ CWnd* pWnd = WindowFromPoint(GetCursorPos());
+ if (pWnd && (dynamic_cast<CToolBar*>(pWnd)))
+ pToolBar = (CToolBar*)pWnd;
+ }
+
+ if ((pToolBar) && (WindowFromPoint(GetCursorPos()) == pToolBar))
+ {
+ // Which toolbar button is the mouse cursor hovering over?
+ int nButton = pToolBar->HitTest();
+ if (nButton >= 0)
+ {
+ int nID = pToolBar->GetCommandID(nButton);
+ // Only update the statusbar if things have changed
+ if (nID != m_nOldID)
+ {
+ if (nID != 0)
+ m_tsStatusText = LoadString(nID);
+ else
+ m_tsStatusText = _T("Ready");
+
+ if (GetStatusBar().IsWindow())
+ SetStatusText();
+ }
+ m_nOldID = nID;
+ }
+ }
+ else
+ {
+ if (m_nOldID != -1)
+ {
+ m_tsStatusText = _T("Ready");
+ SetStatusText();
+ }
+ m_nOldID = -1;
+ }
+ }
+
+ if (m_bShowIndicatorStatus)
+ SetStatusIndicators();
+ }
+ }
+
+ inline void CFrame::OnViewStatusBar()
+ {
+ m_bShowStatusBar = !m_bShowStatusBar;
+ ShowStatusBar(m_bShowStatusBar);
+ }
+
+ inline void CFrame::OnViewToolBar()
+ {
+ m_bShowToolBar = !m_bShowToolBar;
+ ShowToolBar(m_bShowToolBar);
+ }
+
+ inline void CFrame::PreCreate(CREATESTRUCT& cs)
+ {
+ // Set the frame window styles
+ cs.style = WS_OVERLAPPEDWINDOW | WS_VISIBLE;
+
+ // Set the original window position
+ cs.x = m_rcPosition.left;
+ cs.y = m_rcPosition.top;
+ cs.cx = m_rcPosition.Width();
+ cs.cy = m_rcPosition.Height();
+ }
+
+ inline void CFrame::PreRegisterClass(WNDCLASS &wc)
+ {
+ // Set the Window Class
+ wc.lpszClassName = _T("Win32++ Frame");
+ }
+
+ inline void CFrame::RecalcLayout()
+ {
+ CWnd* pView = GetView();
+ if ((!pView) || (!pView->GetHwnd()))
+ return;
+
+ // Resize the status bar
+ if (GetStatusBar().IsWindow() && m_bShowStatusBar)
+ {
+ GetStatusBar().SetWindowPos(NULL, 0, 0, 0, 0, SWP_SHOWWINDOW);
+ GetStatusBar().Invalidate();
+ SetStatusText();
+ }
+
+ // Resize the rebar or toolbar
+ if (IsReBarUsed())
+ {
+ GetReBar().SendMessage(WM_SIZE, 0L, 0L);
+ GetReBar().Invalidate();
+ }
+ else if (m_bUseToolBar && m_bShowToolBar)
+ GetToolBar().SendMessage(TB_AUTOSIZE, 0L, 0L);
+
+ // Resize the View window
+ CRect rClient = GetViewRect();
+ if ((rClient.bottom - rClient.top) >= 0)
+ {
+ int x = rClient.left;
+ int y = rClient.top;
+ int cx = rClient.Width();
+ int cy = rClient.Height();
+
+ pView->SetWindowPos( NULL, x, y, cx, cy, SWP_SHOWWINDOW|SWP_ASYNCWINDOWPOS );
+ }
+
+ // Adjust rebar bands
+ if (IsReBarUsed())
+ {
+ if (GetReBar().GetReBarTheme().UseThemes && GetReBar().GetReBarTheme().BandsLeft)
+ GetReBar().MoveBandsLeft();
+
+ if (IsMenuBarUsed())
+ SetMenuBarBandSize();
+ }
+ }
+
+ inline void CFrame::RemoveMRUEntry(LPCTSTR szMRUEntry)
+ {
+ std::vector<tString>::iterator it;
+ for (it = m_vMRUEntries.begin(); it != m_vMRUEntries.end(); ++it)
+ {
+ if ((*it) == szMRUEntry)
+ {
+ m_vMRUEntries.erase(it);
+ break;
+ }
+ }
+
+ UpdateMRUMenu();
+ }
+
+ inline BOOL CFrame::SaveRegistrySettings()
+ {
+ // Store the window position in the registry
+ if (!m_tsKeyName.empty())
+ {
+ tString tsKeyName = _T("Software\\") + m_tsKeyName + _T("\\Frame Settings");
+ HKEY hKey = NULL;
+
+ try
+ {
+ if (ERROR_SUCCESS != RegCreateKeyEx(HKEY_CURRENT_USER, tsKeyName.c_str(), 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, NULL))
+ throw CWinException(_T("RegCreateKeyEx failed"));
+
+ WINDOWPLACEMENT Wndpl = {0};
+ Wndpl.length = sizeof(WINDOWPLACEMENT);
+
+ if (GetWindowPlacement(Wndpl))
+ {
+ // Get the Frame's window position
+ CRect rc = Wndpl.rcNormalPosition;
+ DWORD dwTop = MAX(rc.top, 0);
+ DWORD dwLeft = MAX(rc.left, 0);
+ DWORD dwWidth = MAX(rc.Width(), 100);
+ DWORD dwHeight = MAX(rc.Height(), 50);
+
+ if (ERROR_SUCCESS != RegSetValueEx(hKey, _T("Top"), 0, REG_DWORD, (LPBYTE)&dwTop, sizeof(DWORD)))
+ throw CWinException(_T("RegSetValueEx failed"));
+ if (ERROR_SUCCESS != RegSetValueEx(hKey, _T("Left"), 0, REG_DWORD, (LPBYTE)&dwLeft, sizeof(DWORD)))
+ throw CWinException(_T("RegSetValueEx failed"));
+ if (ERROR_SUCCESS != RegSetValueEx(hKey, _T("Width"), 0, REG_DWORD, (LPBYTE)&dwWidth, sizeof(DWORD)))
+ throw CWinException(_T("RegSetValueEx failed"));
+ if (ERROR_SUCCESS != RegSetValueEx(hKey, _T("Height"), 0, REG_DWORD, (LPBYTE)&dwHeight, sizeof(DWORD)))
+ throw CWinException(_T("RegSetValueEx failed"));
+ }
+
+ // Store the ToolBar and statusbar states
+ DWORD dwShowToolBar = m_bShowToolBar;
+ DWORD dwShowStatusBar = m_bShowStatusBar;
+
+ if (ERROR_SUCCESS != RegSetValueEx(hKey, _T("ToolBar"), 0, REG_DWORD, (LPBYTE)&dwShowToolBar, sizeof(DWORD)))
+ throw CWinException(_T("RegSetValueEx failed"));
+ if (ERROR_SUCCESS != RegSetValueEx(hKey, _T("StatusBar"), 0, REG_DWORD, (LPBYTE)&dwShowStatusBar, sizeof(DWORD)))
+ throw CWinException(_T("RegSetValueEx failed"));
+
+ RegCloseKey(hKey);
+ }
+
+ catch (const CWinException& e)
+ {
+ TRACE(_T("Failed to save registry settings\n"));
+
+ if (hKey)
+ {
+ // Roll back the registry changes by deleting this subkey
+ RegDeleteKey(HKEY_CURRENT_USER ,tsKeyName.c_str());
+ RegCloseKey(hKey);
+ }
+
+ e.what();
+ return FALSE;
+ }
+
+ // Store the MRU entries in the registry
+ if (m_nMaxMRU > 0)
+ {
+ tString tsKeyName = _T("Software\\") + m_tsKeyName + _T("\\Recent Files");
+ HKEY hKey = NULL;
+
+ try
+ {
+ if (ERROR_SUCCESS != RegCreateKeyEx(HKEY_CURRENT_USER, tsKeyName.c_str(), 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, NULL))
+ throw CWinException(_T("RegCreateKeyEx failed"));
+
+ for (UINT i = 0; i < m_nMaxMRU; ++i)
+ {
+ TCHAR szSubKey[10];
+ wsprintf(szSubKey, _T("File %d\0"), i+1);
+ tString tsPathName;
+ if (i < m_vMRUEntries.size())
+ tsPathName = m_vMRUEntries[i];
+
+ if (ERROR_SUCCESS != RegSetValueEx(hKey, szSubKey, 0, REG_SZ, (LPBYTE)tsPathName.c_str(), (1 + lstrlen(tsPathName.c_str()))*sizeof(TCHAR)))
+ throw CWinException(_T("RegSetValueEx failed"));
+ }
+
+ RegCloseKey(hKey);
+ }
+
+ catch (const CWinException& e)
+ {
+ TRACE(_T("Failed to save registry MRU settings\n"));
+
+ if (hKey)
+ {
+ // Roll back the registry changes by deleting this subkey
+ RegDeleteKey(HKEY_CURRENT_USER ,tsKeyName.c_str());
+ RegCloseKey(hKey);
+ }
+
+ e.what();
+ return FALSE;
+ }
+ }
+ }
+
+ return TRUE;
+ }
+
+ inline void CFrame::SetFrameMenu(INT ID_MENU)
+ {
+ // Sets the frame's menu from a Resouce ID.
+ // A resource ID of 0 removes the menu from the frame.
+ HMENU hMenu = 0;
+ if (ID_MENU != 0)
+ {
+ // Sets the frame's menu from a resource ID.
+ hMenu = ::LoadMenu(GetApp()->GetResourceHandle(), MAKEINTRESOURCE(ID_MENU));
+ assert (hMenu);
+ }
+
+ SetFrameMenu(hMenu);
+ }
+
+ inline void CFrame::SetFrameMenu(HMENU hMenu)
+ {
+ // Sets the frame's menu from a HMENU.
+ m_Menu.Attach(hMenu);
+
+ if (IsMenuBarUsed())
+ {
+ GetMenuBar().SetMenu(GetFrameMenu());
+ BOOL bShow = (hMenu != NULL); // boolean expression
+ ShowMenu(bShow);
+ }
+ else
+ SetMenu(&m_Menu);
+ }
+
+ inline UINT CFrame::SetMenuIcons(const std::vector<UINT>& MenuData, COLORREF crMask, UINT ToolBarID, UINT ToolBarDisabledID)
+ {
+ // Remove any existing menu icons
+ if (m_himlMenu) ImageList_Destroy(m_himlMenu);
+ if (m_himlMenuDis) ImageList_Destroy(m_himlMenuDis);
+ m_himlMenu = NULL;
+ m_himlMenuDis = NULL;
+ m_vMenuIcons.clear();
+
+ // Exit if no ToolBarID is specified
+ if (ToolBarID == 0) return 0;
+
+ // Add the menu icons from the bitmap IDs
+ return AddMenuIcons(MenuData, crMask, ToolBarID, ToolBarDisabledID);
+ }
+
+ inline void CFrame::SetMenuBarBandSize()
+ {
+ // Sets the minimum width of the MenuBar band to the width of the rebar
+ // This prevents other bands from moving to this MenuBar's row.
+
+ CRect rcClient = GetClientRect();
+ CReBar& RB = GetReBar();
+ int nBand = RB.GetBand(GetMenuBar());
+ CRect rcBorder = RB.GetBandBorders(nBand);
+
+ REBARBANDINFO rbbi = {0};
+ rbbi.fMask = RBBIM_CHILDSIZE | RBBIM_SIZE;
+ RB.GetBandInfo(nBand, rbbi);
+
+ int Width;
+ if ((GetReBar().GetReBarTheme().UseThemes) && (GetReBar().GetReBarTheme().LockMenuBand))
+ Width = rcClient.Width() - rcBorder.Width() - 2;
+ else
+ Width = GetMenuBar().GetMaxSize().cx;
+
+ rbbi.cxMinChild = Width;
+ rbbi.cx = Width;
+
+ RB.SetBandInfo(nBand, rbbi);
+ }
+
+ inline void CFrame::SetMenuTheme(MenuTheme& Theme)
+ {
+ m_ThemeMenu.UseThemes = Theme.UseThemes;
+ m_ThemeMenu.clrHot1 = Theme.clrHot1;
+ m_ThemeMenu.clrHot2 = Theme.clrHot2;
+ m_ThemeMenu.clrPressed1 = Theme.clrPressed1;
+ m_ThemeMenu.clrPressed2 = Theme.clrPressed2;
+ m_ThemeMenu.clrOutline = Theme.clrOutline;
+
+ GetMenuBar().SetMenuBarTheme(Theme); // Sets the theme for MenuBar buttons
+ Invalidate();
+ }
+
+ inline void CFrame::SetStatusIndicators()
+ {
+ if (::IsWindow(GetStatusBar()))
+ {
+ LPCTSTR Status1 = (::GetKeyState(VK_CAPITAL) & 0x0001)? _T("\tCAP") : _T("");
+ LPCTSTR Status2 = (::GetKeyState(VK_NUMLOCK) & 0x0001)? _T("\tNUM") : _T("");
+ LPCTSTR Status3 = (::GetKeyState(VK_SCROLL) & 0x0001)? _T("\tSCRL"): _T("");
+
+ // Only update indictors if the text has changed
+ if (Status1 != m_OldStatus[0]) GetStatusBar().SetPartText(1, (Status1));
+ if (Status2 != m_OldStatus[1]) GetStatusBar().SetPartText(2, (Status2));
+ if (Status3 != m_OldStatus[2]) GetStatusBar().SetPartText(3, (Status3));
+
+ m_OldStatus[0] = Status1;
+ m_OldStatus[1] = Status2;
+ m_OldStatus[2] = Status3;
+ }
+ }
+
+ inline void CFrame::SetStatusText()
+ {
+ if (::IsWindow(GetStatusBar()))
+ {
+ // Calculate the width of the text indicators
+ CClientDC dcStatus(&GetStatusBar());
+ CSize csCAP = dcStatus.GetTextExtentPoint32(_T("\tCAP"), lstrlen(_T("\tCAP")));
+ CSize csNUM = dcStatus.GetTextExtentPoint32(_T("\tNUM"), lstrlen(_T("\tNUM")));
+ CSize csSCRL = dcStatus.GetTextExtentPoint32(_T("\tSCRL "), lstrlen(_T("\tSCRL ")));
+
+ // Get the coordinates of the parent window's client area.
+ CRect rcClient = GetClientRect();
+ int width = MAX(300, rcClient.right);
+
+ if (m_bShowIndicatorStatus)
+ {
+ // Create 4 panes
+ GetStatusBar().SetPartWidth(0, width - (csCAP.cx+csNUM.cx+csSCRL.cx+20));
+ GetStatusBar().SetPartWidth(1, csCAP.cx);
+ GetStatusBar().SetPartWidth(2, csNUM.cx);
+ GetStatusBar().SetPartWidth(3, csSCRL.cx);
+
+ SetStatusIndicators();
+ }
+
+ // Place text in the 1st pane
+ GetStatusBar().SetPartText(0, m_tsStatusText.c_str());
+ }
+ }
+
+ inline void CFrame::SetTheme()
+ {
+ // Note: To modify theme colors, override this function in CMainframe,
+ // and make any modifications there.
+
+ // Avoid themes if using less than 16 bit colors
+ CClientDC DesktopDC(NULL);
+ if (DesktopDC.GetDeviceCaps(BITSPIXEL) < 16)
+ m_bUseThemes = FALSE;
+
+ BOOL T = TRUE;
+ BOOL F = FALSE;
+
+ if (m_bUseThemes)
+ {
+ // Set a flag redo SetTheme when the theme changes
+ m_bUpdateTheme = TRUE;
+
+ // Detect the XP theme name
+ WCHAR Name[30] = L"";
+ HMODULE hMod = ::LoadLibrary(_T("uxtheme.dll"));
+ if(hMod)
+ {
+ typedef HRESULT (__stdcall *PFNGETCURRENTTHEMENAME)(LPWSTR pszThemeFileName, int cchMaxNameChars,
+ LPWSTR pszColorBuff, int cchMaxColorChars, LPWSTR pszSizeBuff, int cchMaxSizeChars);
+
+ PFNGETCURRENTTHEMENAME pfn = (PFNGETCURRENTTHEMENAME)GetProcAddress(hMod, "GetCurrentThemeName");
+
+ (*pfn)(0, 0, Name, 30, 0, 0);
+
+ ::FreeLibrary(hMod);
+ }
+
+ enum Themetype{ Modern, Grey, Blue, Silver, Olive };
+
+ int Theme = Grey;
+ if (GetWinVersion() < 2600) // Not for Vista and above
+ {
+ if (0 == wcscmp(L"NormalColor", Name)) Theme = Blue;
+ if (0 == wcscmp(L"Metallic", Name)) Theme = Silver;
+ if (0 == wcscmp(L"HomeStead", Name)) Theme = Olive;
+ }
+ else
+ Theme = Modern;
+
+ switch (Theme)
+ {
+ case Modern:
+ {
+ ToolBarTheme tt = {T, RGB(180, 250, 255), RGB(140, 190, 255), RGB(150, 220, 255), RGB(80, 100, 255), RGB(127, 127, 255)};
+ ReBarTheme tr = {T, RGB(220, 225, 250), RGB(240, 242, 250), RGB(240, 240, 250), RGB(180, 200, 230), F, T, T, T, T, F};
+ MenuTheme tm = {T, RGB(180, 250, 255), RGB(140, 190, 255), RGB(240, 250, 255), RGB(120, 170, 220), RGB(127, 127, 255)};
+
+ GetToolBar().SetToolBarTheme(tt);
+ SetMenuTheme(tm); // Sets the theme for popup menus and MenuBar
+
+ GetReBar().SetReBarTheme(tr);
+ }
+ break;
+
+ case Grey: // A color scheme suitable for 16 bit colors. Suitable for Windows older than XP.
+ {
+ ToolBarTheme tt = {T, RGB(182, 189, 210), RGB(182, 189, 210), RGB(133, 146, 181), RGB(133, 146, 181), RGB(10, 36, 106)};
+ ReBarTheme tr = {T, RGB(212, 208, 200), RGB(212, 208, 200), RGB(230, 226, 222), RGB(220, 218, 208), F, T, T, T, T, F};
+ MenuTheme tm = {T, RGB(182, 189, 210), RGB( 182, 189, 210), RGB(200, 196, 190), RGB(200, 196, 190), RGB(100, 100, 100)};
+
+ GetToolBar().SetToolBarTheme(tt);
+ SetMenuTheme(tm); // Sets the theme for popup menus and MenuBar
+
+ GetReBar().SetReBarTheme(tr);
+ }
+ break;
+ case Blue:
+ {
+ // Used for XP default (blue) color scheme
+ ToolBarTheme tt = {T, RGB(255, 230, 190), RGB(255, 190, 100), RGB(255, 140, 40), RGB(255, 180, 80), RGB(192, 128, 255)};
+ ReBarTheme tr = {T, RGB(150,190,245), RGB(196,215,250), RGB(220,230,250), RGB( 70,130,220), F, T, T, T, T, F};
+ MenuTheme tm = {T, RGB(255, 230, 190), RGB(255, 190, 100), RGB(220,230,250), RGB(150,190,245), RGB(128, 128, 200)};
+
+ GetToolBar().SetToolBarTheme(tt);
+ SetMenuTheme(tm); // Sets the theme for popup menus and MenuBar
+
+ GetReBar().SetReBarTheme(tr);
+ }
+ break;
+
+ case Silver:
+ {
+ // Used for XP Silver color scheme
+ ToolBarTheme tt = {T, RGB(192, 210, 238), RGB(192, 210, 238), RGB(152, 181, 226), RGB(152, 181, 226), RGB(49, 106, 197)};
+ ReBarTheme tr = {T, RGB(225, 220, 240), RGB(240, 240, 245), RGB(245, 240, 255), RGB(160, 155, 180), F, T, T, T, T, F};
+ MenuTheme tm = {T, RGB(196, 215, 250), RGB( 120, 180, 220), RGB(240, 240, 245), RGB(170, 165, 185), RGB(128, 128, 150)};
+
+ GetToolBar().SetToolBarTheme(tt);
+ SetMenuTheme(tm); // Sets the theme for popup menus and MenuBar
+
+ GetReBar().SetReBarTheme(tr);
+ }
+ break;
+
+ case Olive:
+ {
+ // Used for XP Olive color scheme
+ ReBarTheme tr = {T, RGB(215, 216, 182), RGB(242, 242, 230), RGB(249, 255, 227), RGB(178, 191, 145), F, T, T, T, T, F};
+ ToolBarTheme tt = {T, RGB(255, 230, 190), RGB(255, 190, 100), RGB(255, 140, 40), RGB(255, 180, 80), RGB(200, 128, 128)};
+ MenuTheme tm = {T, RGB(255, 230, 190), RGB(255, 190, 100), RGB(249, 255, 227), RGB(178, 191, 145), RGB(128, 128, 128)};
+
+ GetToolBar().SetToolBarTheme(tt);
+ SetMenuTheme(tm); // Sets the theme for popup menus and MenuBar
+
+ GetReBar().SetReBarTheme(tr);
+ }
+ break;
+ }
+ }
+ else
+ {
+ // Use a classic style by default
+ ReBarTheme tr = {T, 0, 0, 0, 0, F, T, T, F, F, F};
+ GetReBar().SetReBarTheme(tr);
+ }
+
+ RecalcLayout();
+ }
+
+ inline void CFrame::SetToolBarImages(COLORREF crMask, UINT ToolBarID, UINT ToolBarHotID, UINT ToolBarDisabledID)
+ // Either sets the imagelist or adds/replaces bitmap depending on ComCtl32.dll version
+ // Assumes the width of the button image = bitmap_size / buttons
+ // Assumes buttons have been already been added via AdddToolBarButton
+ // The colour mask is ignored for 32bit bitmaps, but is required for 24bit bitmaps
+ // The colour mask is often grey RGB(192,192,192) or magenta (255,0,255)
+ // The color mask is ignored for 32bit bitmap resources
+ // The Hot and disabled bitmap resources can be 0
+ {
+ GetToolBar().SetImages(crMask, ToolBarID, ToolBarHotID, ToolBarDisabledID);
+ }
+
+ inline void CFrame::SetupToolBar()
+ {
+ // Use this function to set the Resource IDs for the toolbar(s).
+
+/* // Set the Resource IDs for the toolbar buttons
+ AddToolBarButton( IDM_FILE_NEW );
+ AddToolBarButton( IDM_FILE_OPEN );
+ AddToolBarButton( IDM_FILE_SAVE );
+ AddToolBarButton( 0 ); // Separator
+ AddToolBarButton( IDM_EDIT_CUT );
+ AddToolBarButton( IDM_EDIT_COPY );
+ AddToolBarButton( IDM_EDIT_PASTE );
+ AddToolBarButton( 0 ); // Separator
+ AddToolBarButton( IDM_FILE_PRINT );
+ AddToolBarButton( 0 ); // Separator
+ AddToolBarButton( IDM_HELP_ABOUT );
+*/
+ }
+
+ inline void CFrame::SetView(CWnd& wndView)
+ // Sets or changes the View window displayed within the frame
+ {
+ if (m_pView != &wndView)
+ {
+ // Destroy the existing view window (if any)
+ if (m_pView) m_pView->Destroy();
+
+ // Assign the view window
+ m_pView = &wndView;
+
+ if (m_hWnd)
+ {
+ // The frame is already created, so create and position the new view too
+ assert(GetView()); // Use SetView in CMainFrame's constructor to set the view window
+ GetView()->Create(this);
+ RecalcLayout();
+ }
+ }
+ }
+
+ inline void CFrame::ShowMenu(BOOL bShow)
+ {
+ if (bShow)
+ {
+ if (IsReBarUsed())
+ GetReBar().SendMessage(RB_SHOWBAND, GetReBar().GetBand(GetMenuBar()), TRUE);
+ else
+ SetMenu(&m_Menu);
+ }
+ else
+ {
+ if (IsReBarUsed())
+ GetReBar().SendMessage(RB_SHOWBAND, GetReBar().GetBand(GetMenuBar()), FALSE);
+ else
+ SetMenu(NULL);
+ }
+
+ if (GetReBar().IsWindow())
+ {
+ if (GetReBar().GetReBarTheme().UseThemes && GetReBar().GetReBarTheme().BandsLeft)
+ GetReBar().MoveBandsLeft();
+ }
+
+ // Reposition the Windows
+ RecalcLayout();
+ }
+
+
+
+ inline void CFrame::ShowStatusBar(BOOL bShow)
+ {
+ if (bShow)
+ {
+ m_Menu.CheckMenuItem(IDW_VIEW_STATUSBAR, MF_CHECKED);
+ GetStatusBar().ShowWindow(SW_SHOW);
+ }
+ else
+ {
+ m_Menu.CheckMenuItem(IDW_VIEW_STATUSBAR, MF_UNCHECKED);
+ GetStatusBar().ShowWindow(SW_HIDE);
+ }
+
+ // Reposition the Windows
+ RecalcLayout();
+ }
+
+ inline void CFrame::ShowToolBar(BOOL bShow)
+ {
+ if (bShow)
+ {
+ m_Menu.CheckMenuItem(IDW_VIEW_TOOLBAR, MF_CHECKED);
+ if (IsReBarUsed())
+ GetReBar().SendMessage(RB_SHOWBAND, GetReBar().GetBand(GetToolBar()), TRUE);
+ else
+ GetToolBar().ShowWindow(SW_SHOW);
+ }
+ else
+ {
+ m_Menu.CheckMenuItem(IDW_VIEW_TOOLBAR, MF_UNCHECKED);
+ if (IsReBarUsed())
+ GetReBar().SendMessage(RB_SHOWBAND, GetReBar().GetBand(GetToolBar()), FALSE);
+ else
+ GetToolBar().ShowWindow(SW_HIDE);
+ }
+
+ if (GetReBar().IsWindow())
+ {
+ if (GetReBar().GetReBarTheme().UseThemes && GetReBar().GetReBarTheme().BandsLeft)
+ GetReBar().MoveBandsLeft();
+ }
+
+ // Reposition the Windows
+ RecalcLayout();
+ }
+
+ inline void CFrame::UpdateMRUMenu()
+ {
+ if (0 >= m_nMaxMRU) return;
+
+ // Set the text for the MRU Menu
+ tString tsMRUArray[16];
+ UINT MaxMRUArrayIndex = 0;
+ if (m_vMRUEntries.size() > 0)
+ {
+ for (UINT n = 0; ((n < m_vMRUEntries.size()) && (n <= m_nMaxMRU)); ++n)
+ {
+ tsMRUArray[n] = m_vMRUEntries[n];
+ if (tsMRUArray[n].length() > MAX_MENU_STRING - 10)
+ {
+ // Truncate the string if its too long
+ tsMRUArray[n].erase(0, tsMRUArray[n].length() - MAX_MENU_STRING +10);
+ tsMRUArray[n] = _T("... ") + tsMRUArray[n];
+ }
+
+ // Prefix the string with its number
+ TCHAR tVal[5];
+ wsprintf(tVal, _T("%d "), n+1);
+ tsMRUArray[n] = tVal + tsMRUArray[n];
+ MaxMRUArrayIndex = n;
+ }
+ }
+ else
+ {
+ tsMRUArray[0] = _T("Recent Files");
+ }
+
+ // Set MRU menu items
+ MENUITEMINFO mii = {0};
+ mii.cbSize = GetSizeofMenuItemInfo();
+
+ int nFileItem = 0; // We place the MRU items under the left most menu item
+ CMenu* pFileMenu = GetFrameMenu().GetSubMenu(nFileItem);
+
+ if (pFileMenu)
+ {
+ // Remove all but the first MRU Menu entry
+ for (UINT u = IDW_FILE_MRU_FILE2; u <= IDW_FILE_MRU_FILE1 +16; ++u)
+ {
+ pFileMenu->DeleteMenu(u, MF_BYCOMMAND);
+ }
+
+ int MaxMRUIndex = (int)MIN(MaxMRUArrayIndex, m_nMaxMRU);
+
+ for (int index = MaxMRUIndex; index >= 0; --index)
+ {
+ mii.fMask = MIIM_TYPE | MIIM_ID | MIIM_STATE;
+ mii.fState = (0 == m_vMRUEntries.size())? MFS_GRAYED : 0;
+ mii.fType = MFT_STRING;
+ mii.wID = IDW_FILE_MRU_FILE1 + index;
+ mii.dwTypeData = (LPTSTR)tsMRUArray[index].c_str();
+
+ BOOL bResult;
+ if (index == MaxMRUIndex)
+ // Replace the last MRU entry first
+ bResult = pFileMenu->SetMenuItemInfo(IDW_FILE_MRU_FILE1, &mii, FALSE);
+ else
+ // Insert the other MRU entries next
+ bResult = pFileMenu->InsertMenuItem(IDW_FILE_MRU_FILE1 + index + 1, &mii, FALSE);
+
+ if (!bResult)
+ {
+ TRACE(_T("Failed to set MRU menu item\n"));
+ break;
+ }
+ }
+ }
+
+ DrawMenuBar();
+ }
+
+ inline LRESULT CFrame::WndProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam)
+ {
+ switch (uMsg)
+ {
+ case WM_ACTIVATE:
+ OnActivate(wParam, lParam);
+ return 0L;
+ case WM_CLOSE:
+ OnClose();
+ break;
+ case WM_DESTROY:
+ OnDestroy();
+ return 0L;
+ case WM_ERASEBKGND:
+ return 0L;
+ case WM_HELP:
+ OnHelp();
+ return 0L;
+ case WM_MENUCHAR:
+ return OnMenuChar(wParam, lParam);
+ case WM_MENUSELECT:
+ OnMenuSelect(wParam, lParam);
+ return 0L;
+ case WM_SETFOCUS:
+ OnSetFocus();
+ break;
+ case WM_SIZE:
+ RecalcLayout();
+ return 0L;
+ case WM_SYSCOLORCHANGE:
+ // Changing themes trigger this
+ OnSysColorChange();
+ return 0L;
+ case WM_SYSCOMMAND:
+ return OnSysCommand(wParam, lParam);
+ case WM_TIMER:
+ OnTimer(wParam);
+ return 0L;
+ case WM_DRAWITEM:
+ // Owner draw menu items
+ return OnDrawItem(wParam, lParam);
+ case WM_INITMENUPOPUP:
+ OnInitMenuPopup(wParam, lParam);
+ break;
+ case WM_MEASUREITEM:
+ return OnMeasureItem(wParam, lParam);
+ case WM_EXITMENULOOP:
+ OnExitMenuLoop();
+ break;
+ case UWM_GETMENUTHEME:
+ {
+ MenuTheme& tm = GetMenuTheme();
+ return (LRESULT)&tm;
+ }
+ case UWM_GETREBARTHEME:
+ {
+ ReBarTheme& rm = GetReBarTheme();
+ return (LRESULT)&rm;
+ }
+ case UWM_GETTOOLBARTHEME:
+ {
+ ToolBarTheme& tt = GetToolBarTheme();
+ return (LRESULT)&tt;
+ }
+ } // switch uMsg
+
+ return CWnd::WndProcDefault(uMsg, wParam, lParam);
+ } // LRESULT CFrame::WndProcDefault(...)
+
+
+} // namespace Win32xx
+
+#endif // _WIN32XX_FRAME_H_
diff --git a/mmc_updater/depends/win32cpp/gdi.h b/mmc_updater/depends/win32cpp/gdi.h
new file mode 100644
index 00000000..45141f7b
--- /dev/null
+++ b/mmc_updater/depends/win32cpp/gdi.h
@@ -0,0 +1,3944 @@
+// Win32++ Version 7.2
+// Released: 5th AUgust 2011
+//
+// David Nash
+// email: dnash@bigpond.net.au
+// url: https://sourceforge.net/projects/win32-framework
+//
+//
+// Copyright (c) 2005-2011 David Nash
+//
+// Permission is hereby granted, free of charge, to
+// any person obtaining a copy of this software and
+// associated documentation files (the "Software"),
+// to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify,
+// merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom
+// the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice
+// shall be included in all copies or substantial portions
+// of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
+// OR OTHER DEALINGS IN THE SOFTWARE.
+//
+////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////
+// gdi.h
+// Declaration of the CDC class, and CBitmapInfoPtr class
+
+// The CDC class provides a device context, along with the various associated
+// objects such as Bitmaps, Brushes, Bitmaps, Fonts and Pens. This class
+// handles the creation, selection, de-selection and deletion of these objects
+// automatically. It also automatically deletes or releases the device context
+// itself as appropriate. Any failure to create the new GDI object throws an
+// exception.
+//
+// The CDC class is sufficient for most GDI programming needs. Sometimes
+// however we need to have the GDI object seperated from the device context.
+// Wrapper classes for GDI objects are provided for this purpose. The classes
+// are CBitmap, CBrush, CFont, CPalette, CPen and CRgn. These classes
+// automatically delete the GDI resouce assigned to them when their destructor
+// is called. These wrapper class objects can be attached to the CDC as
+// shown below.
+//
+// Coding Exampe without CDC ...
+// void DrawLine()
+// {
+// HDC hdcClient = ::GetDC(m_hWnd);
+// HDC hdcMem = ::CreateCompatibleDC(hdcClient);
+// HBITMAP hBitmap = ::CreateCompatibleBitmap(hdcClient, cx, cy);
+// HBITMAP hOldBitmap = (HBITMAP)::SelectObject(hdcMem, hBitmap);
+// HPEN hPen = ::CreatePen(PS_SOLID, 1, RGB(255,0,0);
+// HPEN hOldPen = (HPEN)::SelectObject(hdcMem, hPen);
+// ::MoveToEx(hdcMem, 0, 0, NULL);
+// ::LineTo(hdcMem, 50, 50);
+// ::BitBlt(hdcClient, 0, 0, cx, cy, hdcMem, 0, 0);
+// ::SelectObject(hdcMem, hOldPen);
+// ::DeleteObject(hPen);
+// ::SelectObject(hdcMem, hOldBitmap);
+// ::DeleteObject(hBitmap);
+// ::DeleteDC(hdcMem);
+// ::ReleaseDC(m_hWnd, hdcClient);
+// }
+//
+// Coding Example with CDC classes ...
+// void DrawLine()
+// {
+// CClientDC dcClient(this)
+// CMemDC dcMem(&dcClient);
+// CBitmap* pOldBitmap = dcMem.CreateCompatibleBitmap(&dcClient, cx, cy);
+// CPen* pOldPen = CMemDC.CreatePen(PS_SOLID, 1, RGB(255,0,0);
+// CMemDC.MoveTo(0, 0);
+// CMemDC.LineTo(50, 50);
+// dcClient.BitBlt(0, 0, cx, cy, &CMemDC, 0, 0);
+// }
+//
+// Coding Example with CDC classes and CPen ...
+// void DrawLine()
+// {
+// CClientDC dcClient(this)
+// CMemDC CMemDC(&dcClient);
+// CBitmap* pOldBitmap = dcMem.CreateCompatibleBitmap(&dcClient, cx, cy);
+// CPen MyPen(PS_SOLID, 1, RGB(255,0,0));
+// CPen* pOldPen = CMemDC.SelectObject(&MyPen);
+// CMemDC.MoveTo(0, 0);
+// CMemDC.LineTo(50, 50);
+// dcClient.BitBlt(0, 0, cx, cy, &CMemDC, 0, 0);
+// }
+
+// Notes:
+// * When the CDC object drops out of scope, it's destructor is called, releasing
+// or deleting the device context as appropriate.
+// * When the destructor for CBitmap, CBrush, CPalette, CPen and CRgn are called,
+// the destructor is called deleting their GDI object.
+// * When the CDC object' destructor is called, any GDI objects created by one of
+// the CDC member functions (CDC::CreatePen for example) will be deleted.
+// * Bitmaps can only be selected into one device context at a time.
+// * Palettes use SelectPalatte to select them into device the context.
+// * Regions use SelectClipRgn to select them into the device context.
+// * The FromHandle function can be used to convert a GDI handle (HDC, HPEN,
+// HBITMAP etc) to a pointer of the appropriate GDI class (CDC, CPen CBitmap etc).
+// The FromHandle function creates a temporary object unless the HANDLE is already
+// assigned to a GDI class. Temporary objects don't delete their GDI object when
+// their destructor is called.
+// * All the GDI classes are reference counted. This allows functions to safely
+// pass these objects by value, as well as by pointer or by reference.
+
+// The CBitmapInfoPtr class is a convienient wrapper for the BITMAPINFO structure.
+// The size of the BITMAPINFO structure is dependant on the type of HBITMAP, and its
+// space needs to be allocated dynamically. CBitmapInfoPtr automatically allocates
+// and deallocates the memory for the structure. A CBitmapInfoPtr object can be
+// used anywhere in place of a LPBITMAPINFO. LPBITMAPINFO is used in functions like
+// GetDIBits and SetDIBits.
+//
+// Coding example ...
+// CDC MemDC = CreateCompatibleDC(NULL);
+// CBitmapInfoPtr pbmi(hBitmap);
+// MemDC.GetDIBits(hBitmap, 0, pbmi->bmiHeader.biHeight, NULL, pbmi, DIB_RGB_COLORS);
+
+#ifndef _WIN32XX_GDI_H_
+#define _WIN32XX_GDI_H_
+
+#include "wincore.h"
+
+// Disable macros from Windowsx.h
+#undef CopyRgn
+
+namespace Win32xx
+{
+
+ /////////////////////////////////////////////////////////////////
+ // Declarations for some global functions in the Win32xx namespace
+ //
+#ifndef _WIN32_WCE
+ void GrayScaleBitmap(CBitmap* pbmSource);
+ void TintBitmap(CBitmap* pbmSource, int cRed, int cGreen, int cBlue);
+ HIMAGELIST CreateDisabledImageList(HIMAGELIST himlNormal);
+#endif
+
+ ///////////////////////////////////////////////
+ // Declarations for the CGDIObject class
+ //
+ class CGDIObject
+ {
+ friend CBitmap* FromHandle(HBITMAP hBitmap);
+ friend CBrush* FromHandle(HBRUSH hBrush);
+ friend CDC* FromHandle(HDC hDC);
+ friend CFont* FromHandle(HFONT hFont);
+ friend CPalette* FromHandle(HPALETTE hPalette);
+ friend CPen* FromHandle(HPEN hPen);
+ friend CRgn* FromHandle(HRGN hRgn);
+
+ public:
+ struct DataMembers // A structure that contains the data members for CGDIObject
+ {
+ HGDIOBJ hGDIObject;
+ long Count;
+ BOOL bRemoveObject;
+ };
+ CGDIObject();
+ CGDIObject(const CGDIObject& rhs);
+ virtual ~CGDIObject();
+ CGDIObject& operator = ( const CGDIObject& rhs );
+ void operator = (HGDIOBJ hObject);
+
+ void Attach(HGDIOBJ hObject);
+ HGDIOBJ Detach();
+ HGDIOBJ GetHandle() const;
+ int GetObject(int nCount, LPVOID pObject) const;
+
+ protected:
+ DataMembers* m_pData;
+
+ private:
+ void AddToMap();
+ BOOL RemoveFromMap();
+ void Release();
+ };
+
+
+ ///////////////////////////////////////////////
+ // Declarations for the CBitmap class
+ //
+ class CBitmap : public CGDIObject
+ {
+ public:
+ CBitmap();
+ CBitmap(HBITMAP hBitmap);
+ CBitmap(LPCTSTR lpstr);
+ CBitmap(int nID);
+ operator HBITMAP() const;
+ ~CBitmap();
+
+ // Create and load methods
+ BOOL LoadBitmap(LPCTSTR lpszName);
+ BOOL LoadBitmap(int nID);
+ BOOL LoadImage(LPCTSTR lpszName, int cxDesired, int cyDesired, UINT fuLoad);
+ BOOL LoadImage(UINT nID, int cxDesired, int cyDesired, UINT fuLoad);
+ BOOL LoadOEMBitmap(UINT nIDBitmap);
+ HBITMAP CreateBitmap(int nWidth, int nHeight, UINT nPlanes, UINT nBitsPerPixel, LPCVOID lpBits);
+ HBITMAP CreateCompatibleBitmap(CDC* pDC, int nWidth, int nHeight);
+ HBITMAP CreateDIBSection(CDC* pDC, CONST BITMAPINFO* lpbmi, UINT uColorUse, LPVOID* ppvBits, HANDLE hSection, DWORD dwOffset);
+
+#ifndef _WIN32_WCE
+ HBITMAP CreateDIBitmap(CDC* pDC, CONST BITMAPINFOHEADER* lpbmih, DWORD dwInit, LPCVOID lpbInit, CONST BITMAPINFO* lpbmi, UINT uColorUse);
+ HBITMAP CreateMappedBitmap(UINT nIDBitmap, UINT nFlags = 0, LPCOLORMAP lpColorMap = NULL, int nMapSize = 0);
+ HBITMAP CreateBitmapIndirect(LPBITMAP lpBitmap);
+ int GetDIBits(CDC* pDC, UINT uStartScan, UINT cScanLines, LPVOID lpvBits, LPBITMAPINFO lpbmi, UINT uColorUse) const;
+ int SetDIBits(CDC* pDC, UINT uStartScan, UINT cScanLines, CONST VOID* lpvBits, CONST BITMAPINFO* lpbmi, UINT uColorUse);
+ CSize GetBitmapDimensionEx() const;
+ CSize SetBitmapDimensionEx(int nWidth, int nHeight);
+#endif // !_WIN32_WCE
+
+ // Attributes
+ BITMAP GetBitmapData() const;
+ };
+
+
+ ///////////////////////////////////////////////
+ // Declarations for the CBrush class
+ //
+ class CBrush : public CGDIObject
+ {
+ public:
+ CBrush();
+ CBrush(HBRUSH hBrush);
+ CBrush(COLORREF crColor);
+ operator HBRUSH() const;
+ ~CBrush();
+
+ HBRUSH CreateSolidBrush(COLORREF crColor);
+ HBRUSH CreatePatternBrush(CBitmap* pBitmap);
+ LOGBRUSH GetLogBrush() const;
+
+#ifndef _WIN32_WCE
+ HBRUSH CreateHatchBrush(int nIndex, COLORREF crColor);
+ HBRUSH CreateBrushIndirect(LPLOGBRUSH lpLogBrush);
+ HBRUSH CreateDIBPatternBrush(HGLOBAL hglbDIBPacked, UINT fuColorSpec);
+ HBRUSH CreateDIBPatternBrushPt(LPCVOID lpPackedDIB, UINT nUsage);
+#endif // !defined(_WIN32_WCE)
+
+ };
+
+
+ ///////////////////////////////////////////////
+ // Declarations for the CFont class
+ //
+ class CFont : public CGDIObject
+ {
+ public:
+ CFont();
+ CFont(HFONT hFont);
+ CFont(const LOGFONT* lpLogFont);
+ operator HFONT() const;
+ ~CFont();
+
+ // Create methods
+ HFONT CreateFontIndirect(const LOGFONT* lpLogFont);
+ HFONT CreatePointFont(int nPointSize, LPCTSTR lpszFaceName, CDC* pDC = NULL, BOOL bBold = FALSE, BOOL bItalic = FALSE);
+ HFONT CreatePointFontIndirect(const LOGFONT* lpLogFont, CDC* pDC = NULL);
+
+#ifndef _WIN32_WCE
+ HFONT CreateFont(int nHeight, int nWidth, int nEscapement,
+ int nOrientation, int nWeight, DWORD dwItalic, DWORD dwUnderline,
+ DWORD dwStrikeOut, DWORD dwCharSet, DWORD dwOutPrecision,
+ DWORD dwClipPrecision, DWORD dwQuality, DWORD dwPitchAndFamily,
+ LPCTSTR lpszFacename);
+#endif // #ifndef _WIN32_WCE
+
+ // Attributes
+ LOGFONT GetLogFont() const;
+ };
+
+
+ ///////////////////////////////////////////////
+ // Declarations for the CPalette class
+ //
+ class CPalette : public CGDIObject
+ {
+ public:
+ CPalette();
+ CPalette(HPALETTE hPalette);
+ operator HPALETTE() const;
+ ~CPalette();
+
+ // Create methods
+ HPALETTE CreatePalette(LPLOGPALETTE lpLogPalette);
+
+#ifndef _WIN32_WCE
+ HPALETTE CreateHalftonePalette(CDC* pDC);
+#endif // !_WIN32_WCE
+
+ // Attributes
+ int GetEntryCount() const;
+ UINT GetPaletteEntries(UINT nStartIndex, UINT nNumEntries, LPPALETTEENTRY lpPaletteColors) const;
+ UINT SetPaletteEntries(UINT nStartIndex, UINT nNumEntries, LPPALETTEENTRY lpPaletteColors);
+
+ // Operations
+#ifndef _WIN32_WCE
+ BOOL ResizePalette(UINT nNumEntries);
+ void AnimatePalette(UINT nStartIndex, UINT nNumEntries, LPPALETTEENTRY lpPaletteColors);
+#endif // !_WIN32_WCE
+
+ UINT GetNearestPaletteIndex (COLORREF crColor) const;
+
+ };
+
+
+ ///////////////////////////////////////////////
+ // Declarations for the CPen class
+ //
+ class CPen : public CGDIObject
+ {
+ public:
+ CPen();
+ CPen(HPEN hPen);
+ CPen(int nPenStyle, int nWidth, COLORREF crColor);
+#ifndef _WIN32_WCE
+ CPen(int nPenStyle, int nWidth, const LOGBRUSH* pLogBrush, int nStyleCount = 0, const DWORD* lpStyle = NULL);
+#endif // !_WIN32_WCE
+ operator HPEN() const;
+ ~CPen();
+
+ HPEN CreatePen(int nPenStyle, int nWidth, COLORREF crColor);
+ HPEN CreatePenIndirect(LPLOGPEN lpLogPen);
+ LOGPEN GetLogPen() const;
+
+#ifndef _WIN32_WCE
+ HPEN ExtCreatePen(int nPenStyle, int nWidth, const LOGBRUSH* pLogBrush, int nStyleCount = 0, const DWORD* lpStyle = NULL);
+ EXTLOGPEN GetExtLogPen() const;
+#endif // !_WIN32_WCE
+
+ };
+
+
+ ///////////////////////////////////////////////
+ // Declarations for the CRgn class
+ //
+ class CRgn : public CGDIObject
+ {
+ public:
+ CRgn();
+ CRgn(HRGN hRgn);
+ operator HRGN() const;
+ ~CRgn ();
+
+ // Create methods
+ HRGN CreateRectRgn(int x1, int y1, int x2, int y2);
+ HRGN CreateRectRgnIndirect(const RECT& rc);
+ HRGN CreateFromData(const XFORM* lpXForm, int nCount, const RGNDATA* pRgnData);
+
+#ifndef _WIN32_WCE
+ HRGN CreateEllipticRgn(int x1, int y1, int x2, int y2);
+ HRGN CreateEllipticRgnIndirect(const RECT& rc);
+ HRGN CreatePolygonRgn(LPPOINT lpPoints, int nCount, int nMode);
+ HRGN CreatePolyPolygonRgn(LPPOINT lpPoints, LPINT lpPolyCounts, int nCount, int nPolyFillMode);
+ HRGN CreateRoundRectRgn(int x1, int y1, int x2, int y2, int x3, int y3);
+ HRGN CreateFromPath(HDC hDC);
+#endif // !_WIN32_WCE
+
+ // Operations
+ void SetRectRgn(int x1, int y1, int x2, int y2);
+ void SetRectRgn(const RECT& rc);
+ int CombineRgn(CRgn* pRgnSrc1, CRgn* pRgnSrc2, int nCombineMode);
+ int CombineRgn(CRgn* pRgnSrc, int nCombineMode);
+ int CopyRgn(CRgn* pRgnSrc);
+ BOOL EqualRgn(CRgn* pRgn) const;
+ int OffsetRgn(int x, int y);
+ int OffsetRgn(POINT& pt);
+ int GetRgnBox(RECT& rc) const;
+ BOOL PtInRegion(int x, int y) const;
+ BOOL PtInRegion(POINT& pt) const;
+ BOOL RectInRegion(const RECT& rc) const;
+ int GetRegionData(LPRGNDATA lpRgnData, int nDataSize) const;
+ };
+
+
+ ///////////////////////////////////////////////
+ // Declarations for the CDC class
+ //
+ class CDC
+ {
+ friend class CWinApp;
+ friend class CWnd;
+ friend CDC* FromHandle(HDC hDC);
+
+ public:
+ struct DataMembers // A structure that contains the data members for CDC
+ {
+ std::vector<GDIPtr> m_vGDIObjects; // Smart pointers to internally created Bitmaps, Brushes, Fonts, Bitmaps and Regions
+ HDC hDC; // The HDC belonging to this CDC
+ long Count; // Reference count
+ BOOL bRemoveHDC; // Delete/Release the HDC on destruction
+ HWND hWnd; // The HWND of a Window or Client window DC
+ int nSavedDCState; // The save state of the HDC.
+ };
+
+ CDC(); // Constructs a new CDC without assigning a HDC
+ CDC(HDC hDC, HWND hWnd = 0); // Assigns a HDC to a new CDC
+ CDC(const CDC& rhs); // Constructs a new copy of the CDC
+ virtual ~CDC();
+ operator HDC() const { return m_pData->hDC; } // Converts a CDC to a HDC
+ CDC& operator = (const CDC& rhs); // Assigns a CDC to an existing CDC
+
+ void Attach(HDC hDC, HWND hWnd = 0);
+ void Destroy();
+ HDC Detach();
+ HDC GetHDC() const { return m_pData->hDC; }
+ CPalette* SelectPalette(const CPalette* pPalette, BOOL bForceBkgnd);
+ CBitmap* SelectObject(const CBitmap* pBitmap);
+ CBrush* SelectObject(const CBrush* pBrush);
+ CFont* SelectObject(const CFont* pFont);
+ CPalette* SelectObject(const CPalette* pPalette);
+ CPen* SelectObject(const CPen* pPen);
+
+#ifndef _WIN32_WCE
+ void operator = (const HDC hDC);
+#endif
+
+ // Initialization
+ BOOL CreateCompatibleDC(CDC* pDC);
+ BOOL CreateDC(LPCTSTR lpszDriver, LPCTSTR lpszDevice, LPCTSTR lpszOutput, const DEVMODE* pInitData);
+ int GetDeviceCaps(int nIndex) const;
+#ifndef _WIN32_WCE
+ BOOL CreateIC(LPCTSTR lpszDriver, LPCTSTR lpszDevice, LPCTSTR lpszOutput, const DEVMODE* pInitData);
+#endif
+
+ // Create and Select Bitmaps
+ CBitmap* CreateBitmap(int cx, int cy, UINT Planes, UINT BitsPerPixel, LPCVOID pvColors);
+ CBitmap* CreateCompatibleBitmap(CDC* pDC, int cx, int cy);
+ CBitmap* CreateDIBSection(CDC* pDC, const BITMAPINFO& bmi, UINT iUsage, LPVOID *ppvBits,
+ HANDLE hSection, DWORD dwOffset);
+ BITMAP GetBitmapData() const;
+ CBitmap* LoadBitmap(UINT nID);
+ CBitmap* LoadBitmap(LPCTSTR lpszName);
+ CBitmap* LoadImage(UINT nID, int cxDesired, int cyDesired, UINT fuLoad);
+ CBitmap* LoadImage(LPCTSTR lpszName, int cxDesired, int cyDesired, UINT fuLoad);
+ CBitmap* LoadOEMBitmap(UINT nIDBitmap); // for OBM_/OCR_/OIC
+
+#ifndef _WIN32_WCE
+ CBitmap* CreateBitmapIndirect(LPBITMAP pBitmap);
+ CBitmap* CreateDIBitmap(CDC* pDC, const BITMAPINFOHEADER& bmih, DWORD fdwInit, LPCVOID lpbInit,
+ BITMAPINFO& bmi, UINT fuUsage);
+ CBitmap* CreateMappedBitmap(UINT nIDBitmap, UINT nFlags /*= 0*/, LPCOLORMAP lpColorMap /*= NULL*/, int nMapSize /*= 0*/);
+#endif
+
+ // Create and Select Brushes
+ CBrush* CreatePatternBrush(CBitmap* pBitmap);
+ CBrush* CreateSolidBrush(COLORREF rbg);
+ LOGBRUSH GetLogBrush() const;
+
+#ifndef _WIN32_WCE
+ CBrush* CreateBrushIndirect(LPLOGBRUSH pLogBrush);
+ CBrush* CreateHatchBrush(int fnStyle, COLORREF rgb);
+ CBrush* CreateDIBPatternBrush(HGLOBAL hglbDIBPacked, UINT fuColorSpec);
+ CBrush* CreateDIBPatternBrushPt(LPCVOID lpPackedDIB, UINT iUsage);
+#endif
+
+ // Create and Select Fonts
+ CFont* CreateFontIndirect(LPLOGFONT plf);
+ LOGFONT GetLogFont() const;
+
+#ifndef _WIN32_WCE
+ CFont* CreateFont(int nHeight, int nWidth, int nEscapement, int nOrientation, int fnWeight,
+ DWORD fdwItalic, DWORD fdwUnderline, DWORD fdwStrikeOut, DWORD fdwCharSet,
+ DWORD fdwOutputPrecision, DWORD fdwClipPrecision, DWORD fdwQuality,
+ DWORD fdwPitchAndFamily, LPCTSTR lpszFace);
+#endif
+
+ // Create and Select Pens
+ CPen* CreatePen(int nStyle, int nWidth, COLORREF rgb);
+ CPen* CreatePenIndirect(LPLOGPEN pLogPen);
+ LOGPEN GetLogPen() const;
+
+ // Create Select Regions
+ int CreateRectRgn(int left, int top, int right, int bottom);
+ int CreateRectRgnIndirect(const RECT& rc);
+ int CreateFromData(const XFORM* Xform, DWORD nCount, const RGNDATA *pRgnData);
+#ifndef _WIN32_WCE
+ int CreateEllipticRgn(int left, int top, int right, int bottom);
+ int CreateEllipticRgnIndirect(const RECT& rc);
+ int CreatePolygonRgn(LPPOINT ppt, int cPoints, int fnPolyFillMode);
+ int CreatePolyPolygonRgn(LPPOINT ppt, LPINT pPolyCounts, int nCount, int fnPolyFillMode);
+#endif
+
+ // Wrappers for WinAPI functions
+
+ // Point and Line Drawing Functions
+ CPoint GetCurrentPosition() const;
+ CPoint MoveTo(int x, int y) const;
+ CPoint MoveTo(POINT pt) const;
+ BOOL LineTo(int x, int y) const;
+ BOOL LineTo(POINT pt) const;
+ COLORREF GetPixel(int x, int y) const;
+ COLORREF GetPixel(POINT pt) const;
+ COLORREF SetPixel(int x, int y, COLORREF crColor) const;
+ COLORREF SetPixel(POINT pt, COLORREF crColor) const;
+#ifndef _WIN32_WCE
+ BOOL Arc(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4) const;
+ BOOL Arc(RECT& rc, POINT ptStart, POINT ptEnd) const;
+ BOOL ArcTo(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4) const;
+ BOOL ArcTo(RECT& rc, POINT ptStart, POINT ptEnd) const;
+ BOOL AngleArc(int x, int y, int nRadius, float fStartAngle, float fSweepAngle) const;
+ int GetArcDirection() const;
+ int SetArcDirection(int nArcDirection) const;
+ BOOL PolyDraw(const POINT* lpPoints, const BYTE* lpTypes, int nCount) const;
+ BOOL Polyline(LPPOINT lpPoints, int nCount) const;
+ BOOL PolyPolyline(const POINT* lpPoints, const DWORD* lpPolyPoints, int nCount) const;
+ BOOL PolylineTo(const POINT* lpPoints, int nCount) const;
+ BOOL PolyBezier(const POINT* lpPoints, int nCount) const;
+ BOOL PolyBezierTo(const POINT* lpPoints, int nCount) const;
+ BOOL SetPixelV(int x, int y, COLORREF crColor) const;
+ BOOL SetPixelV(POINT pt, COLORREF crColor) const;
+#endif
+
+ // Shape Drawing Functions
+ void DrawFocusRect(const RECT& rc) const;
+ BOOL Ellipse(int x1, int y1, int x2, int y2) const;
+ BOOL Ellipse(const RECT& rc) const;
+ BOOL Polygon(LPPOINT lpPoints, int nCount) const;
+ BOOL Rectangle(int x1, int y1, int x2, int y2) const;
+ BOOL Rectangle(const RECT& rc) const;
+ BOOL RoundRect(int x1, int y1, int x2, int y2, int nWidth, int nHeight) const;
+ BOOL RoundRect(const RECT& rc, int nWidth, int nHeight) const;
+
+#ifndef _WIN32_WCE
+ BOOL Chord(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4) const;
+ BOOL Chord(const RECT& rc, POINT ptStart, POINT ptEnd) const;
+ BOOL Pie(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4) const;
+ BOOL Pie(const RECT& rc, POINT ptStart, POINT ptEnd) const;
+ BOOL PolyPolygon(LPPOINT lpPoints, LPINT lpPolyCounts, int nCount) const;
+#endif
+
+ // Fill and Image Drawing functions
+ BOOL FillRect(const RECT& rc, CBrush* pBrushr) const;
+ BOOL InvertRect(const RECT& rc) const;
+ BOOL DrawIconEx(int xLeft, int yTop, HICON hIcon, int cxWidth, int cyWidth, UINT istepIfAniCur, CBrush* pFlickerFreeDraw, UINT diFlags) const;
+ BOOL DrawEdge(const RECT& rc, UINT nEdge, UINT nFlags) const;
+ BOOL DrawFrameControl(const RECT& rc, UINT nType, UINT nState) const;
+ BOOL FillRgn(CRgn* pRgn, CBrush* pBrush) const;
+ void GradientFill(COLORREF Color1, COLORREF Color2, const RECT& rc, BOOL bVertical);
+ void SolidFill(COLORREF Color, const RECT& rc);
+
+#ifndef _WIN32_WCE
+ BOOL DrawIcon(int x, int y, HICON hIcon) const;
+ BOOL DrawIcon(POINT point, HICON hIcon) const;
+ BOOL FrameRect(const RECT& rc, CBrush* pBrush) const;
+ BOOL PaintRgn(CRgn* pRgn) const;
+#endif
+
+ // Bitmap Functions
+ void DrawBitmap(int x, int y, int cx, int cy, CBitmap& Bitmap, COLORREF clrMask);
+ int StretchDIBits(int XDest, int YDest, int nDestWidth, int nDestHeight, int XSrc, int YSrc, int nSrcWidth,
+ int nSrcHeight, CONST VOID *lpBits, BITMAPINFO& bi, UINT iUsage, DWORD dwRop) const;
+ BOOL PatBlt(int x, int y, int nWidth, int nHeight, DWORD dwRop) const;
+ BOOL BitBlt(int x, int y, int nWidth, int nHeight, CDC* pSrcDC, int xSrc, int ySrc, DWORD dwRop) const;
+ BOOL StretchBlt(int x, int y, int nWidth, int nHeight, CDC* pSrcDC, int xSrc, int ySrc, int nSrcWidth, int nSrcHeight, DWORD dwRop) const;
+
+#ifndef _WIN32_WCE
+ int GetDIBits(CBitmap* pBitmap, UINT uStartScan, UINT cScanLines, LPVOID lpvBits, LPBITMAPINFO lpbi, UINT uUsage) const;
+ int SetDIBits(CBitmap* pBitmap, UINT uStartScan, UINT cScanLines, CONST VOID *lpvBits, LPBITMAPINFO lpbi, UINT fuColorUse) const;
+ int GetStretchBltMode() const;
+ int SetStretchBltMode(int iStretchMode) const;
+ BOOL FloodFill(int x, int y, COLORREF crColor) const;
+ BOOL ExtFloodFill(int x, int y, COLORREF crColor, UINT nFillType) const;
+#endif
+
+ // Brush Functions
+#ifdef GetDCBrushColor
+ COLORREF GetDCBrushColor() const;
+ COLORREF SetDCBrushColor(COLORREF crColor) const;
+#endif
+
+ // Clipping Functions
+ int ExcludeClipRect(int Left, int Top, int Right, int BottomRect);
+ int ExcludeClipRect(const RECT& rc);
+ int GetClipBox(RECT& rc);
+ int GetClipRgn(HRGN hrgn);
+ int IntersectClipRect(int Left, int Top, int Right, int Bottom);
+ int IntersectClipRect(const RECT& rc);
+ BOOL RectVisible(const RECT& rc);
+ int SelectClipRgn(CRgn* pRgn);
+
+#ifndef _WIN32_WCE
+ int ExtSelectClipRgn(CRgn* pRgn, int fnMode);
+ int OffsetClipRgn(int nXOffset, int nYOffset);
+ BOOL PtVisible(int X, int Y);
+#endif
+
+ // Co-ordinate Functions
+#ifndef _WIN32_WCE
+ BOOL DPtoLP(LPPOINT lpPoints, int nCount) const;
+ BOOL DPtoLP(RECT& rc) const;
+ BOOL LPtoDP(LPPOINT lpPoints, int nCount) const;
+ BOOL LPtoDP(RECT& rc) const;
+#endif
+
+ // Layout Functions
+ DWORD GetLayout() const;
+ DWORD SetLayout(DWORD dwLayout) const;
+
+ // Mapping functions
+#ifndef _WIN32_WCE
+ int GetMapMode() const;
+ int SetMapMode(int nMapMode) const;
+ BOOL GetViewportOrgEx(LPPOINT lpPoint) const;
+ BOOL SetViewportOrgEx(int x, int y, LPPOINT lpPoint = NULL) const;
+ BOOL SetViewportOrgEx(POINT point, LPPOINT lpPointRet = NULL) const;
+ BOOL OffsetViewportOrgEx(int nWidth, int nHeight, LPPOINT lpPoint = NULL) const;
+ BOOL GetViewportExtEx(LPSIZE lpSize) const;
+ BOOL SetViewportExtEx(int x, int y, LPSIZE lpSize) const;
+ BOOL SetViewportExtEx(SIZE size, LPSIZE lpSizeRet) const;
+ BOOL ScaleViewportExtEx(int xNum, int xDenom, int yNum, int yDenom, LPSIZE lpSize) const;
+ BOOL OffsetWindowOrg(int nWidth, int nHeight, LPPOINT lpPoint) const;
+ BOOL GetWindowExtEx(LPSIZE lpSize) const;
+ BOOL SetWindowExtEx(int x, int y, LPSIZE lpSize) const;
+ BOOL SetWindowExtEx(SIZE size, LPSIZE lpSizeRet) const;
+ BOOL ScaleWindowExtEx(int xNum, int xDenom, int yNum, int yDenom, LPSIZE lpSize) const;
+ BOOL GetWindowOrgEx(LPPOINT lpPoint) const;
+ BOOL SetWindowOrgEx(int x, int y, LPPOINT lpPoint) const;
+ BOOL SetWindowOrgEx(POINT point, LPPOINT lpPointRet) const;
+ BOOL OffsetWindowOrgEx(int nWidth, int nHeight, LPPOINT lpPoint) const;
+#endif
+
+ // Printer Functions
+ int StartDoc(LPDOCINFO lpDocInfo) const;
+ int EndDoc() const;
+ int StartPage() const;
+ int EndPage() const;
+ int AbortDoc() const;
+ int SetAbortProc(BOOL (CALLBACK* lpfn)(HDC, int)) const;
+
+ // Text Functions
+ int DrawText(LPCTSTR lpszString, int nCount, LPRECT lprc, UINT nFormat) const;
+ BOOL ExtTextOut(int x, int y, UINT nOptions, LPCRECT lprc, LPCTSTR lpszString, int nCount = -1, LPINT lpDxWidths = NULL) const;
+ COLORREF GetBkColor() const;
+ int GetBkMode() const;
+ UINT GetTextAlign() const;
+ int GetTextFace(int nCount, LPTSTR lpszFacename) const;
+ COLORREF GetTextColor() const;
+ BOOL GetTextMetrics(TEXTMETRIC& Metrics) const;
+ COLORREF SetBkColor(COLORREF crColor) const;
+ int SetBkMode(int iBkMode) const;
+ UINT SetTextAlign(UINT nFlags) const;
+ COLORREF SetTextColor(COLORREF crColor) const;
+
+#ifndef _WIN32_WCE
+ int DrawTextEx(LPTSTR lpszString, int nCount, LPRECT lprc, UINT nFormat, LPDRAWTEXTPARAMS lpDTParams) const;
+ CSize GetTabbedTextExtent(LPCTSTR lpszString, int nCount, int nTabPositions, LPINT lpnTabStopPositions) const;
+ int GetTextCharacterExtra() const;
+ CSize GetTextExtentPoint32(LPCTSTR lpszString, int nCount) const;
+ BOOL GrayString(CBrush* pBrush, GRAYSTRINGPROC lpOutputFunc, LPARAM lpData, int nCount, int x, int y, int nWidth, int nHeight) const;
+ int SetTextCharacterExtra(int nCharExtra) const;
+ int SetTextJustification(int nBreakExtra, int nBreakCount) const;
+ CSize TabbedTextOut(int x, int y, LPCTSTR lpszString, int nCount, int nTabPositions, LPINT lpnTabStopPositions, int nTabOrigin) const;
+ BOOL TextOut(int x, int y, LPCTSTR lpszString, int nCount = -1) const;
+#endif
+
+ private:
+ void AddToMap();
+ static CDC* AddTempHDC(HDC hDC, HWND hWnd);
+ void Release();
+ BOOL RemoveFromMap();
+
+ DataMembers* m_pData; // pointer to the class's data members
+ };
+
+ class CClientDC : public CDC
+ {
+ public:
+ CClientDC(const CWnd* pWnd)
+ {
+ if (pWnd) assert(pWnd->IsWindow());
+ HWND hWnd = pWnd? pWnd->GetHwnd() : GetDesktopWindow();
+ Attach(::GetDC(hWnd), hWnd);
+ }
+ virtual ~CClientDC() {}
+ };
+
+ class CMemDC : public CDC
+ {
+ public:
+ CMemDC(const CDC* pDC)
+ {
+ if (pDC) assert(pDC->GetHDC());
+ HDC hDC = pDC? pDC->GetHDC() : NULL;
+ Attach(::CreateCompatibleDC(hDC));
+ }
+ virtual ~CMemDC() {}
+ };
+
+ class CPaintDC : public CDC
+ {
+ public:
+ CPaintDC(const CWnd* pWnd)
+ {
+ assert(pWnd->IsWindow());
+ m_hWnd = pWnd->GetHwnd();
+ Attach(::BeginPaint(pWnd->GetHwnd(), &m_ps), m_hWnd);
+ }
+
+ virtual ~CPaintDC() { ::EndPaint(m_hWnd, &m_ps); }
+
+ private:
+ HWND m_hWnd;
+ PAINTSTRUCT m_ps;
+ };
+
+ class CWindowDC : public CDC
+ {
+ public:
+ CWindowDC(const CWnd* pWnd)
+ {
+ if (pWnd) assert(pWnd->IsWindow());
+ HWND hWnd = pWnd? pWnd->GetHwnd() : GetDesktopWindow();
+ Attach(::GetWindowDC(hWnd), hWnd);
+ }
+ virtual ~CWindowDC() {}
+ };
+
+#ifndef _WIN32_WCE
+ class CMetaFileDC : public CDC
+ {
+ public:
+ CMetaFileDC() : m_hMF(0), m_hEMF(0) {}
+ virtual ~CMetaFileDC()
+ {
+ if (m_hMF)
+ {
+ ::CloseMetaFile(GetHDC());
+ ::DeleteMetaFile(m_hMF);
+ }
+ if (m_hEMF)
+ {
+ ::CloseEnhMetaFile(GetHDC());
+ ::DeleteEnhMetaFile(m_hEMF);
+ }
+ }
+ void Create(LPCTSTR lpszFilename = NULL) { Attach(::CreateMetaFile(lpszFilename)); }
+ void CreateEnhanced(CDC* pDCRef, LPCTSTR lpszFileName, LPCRECT lpBounds, LPCTSTR lpszDescription)
+ {
+ HDC hDC = pDCRef? pDCRef->GetHDC() : NULL;
+ ::CreateEnhMetaFile(hDC, lpszFileName, lpBounds, lpszDescription);
+ assert(GetHDC());
+ }
+ HMETAFILE Close() { return ::CloseMetaFile(GetHDC()); }
+ HENHMETAFILE CloseEnhanced() { return ::CloseEnhMetaFile(GetHDC()); }
+
+ private:
+ HMETAFILE m_hMF;
+ HENHMETAFILE m_hEMF;
+ };
+#endif
+
+
+ ///////////////////////////////////////////////
+ // Declarations for the CBitmapInfoPtr class
+ // The CBitmapInfoPtr class is a convienient wrapper for the BITMAPINFO structure.
+ class CBitmapInfoPtr
+ {
+ public:
+ CBitmapInfoPtr(CBitmap* pBitmap)
+ {
+ BITMAP bmSource = pBitmap->GetBitmapData();
+
+ // Convert the color format to a count of bits.
+ WORD cClrBits = (WORD)(bmSource.bmPlanes * bmSource.bmBitsPixel);
+ if (cClrBits == 1) cClrBits = 1;
+ else if (cClrBits <= 4) cClrBits = 4;
+ else if (cClrBits <= 8) cClrBits = 8;
+ else if (cClrBits <= 16) cClrBits = 16;
+ else if (cClrBits <= 24) cClrBits = 24;
+ else cClrBits = 32;
+
+ // Allocate memory for the BITMAPINFO structure.
+ UINT uQuadSize = (cClrBits == 24)? 0 : sizeof(RGBQUAD) * (int)(1 << cClrBits);
+ m_bmi.assign(sizeof(BITMAPINFOHEADER) + uQuadSize, 0);
+ m_pbmiArray = (LPBITMAPINFO) &m_bmi[0];
+
+ m_pbmiArray->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+ m_pbmiArray->bmiHeader.biHeight = bmSource.bmHeight;
+ m_pbmiArray->bmiHeader.biWidth = bmSource.bmWidth;
+ m_pbmiArray->bmiHeader.biPlanes = bmSource.bmPlanes;
+ m_pbmiArray->bmiHeader.biBitCount = bmSource.bmBitsPixel;
+ m_pbmiArray->bmiHeader.biCompression = BI_RGB;
+ if (cClrBits < 24)
+ m_pbmiArray->bmiHeader.biClrUsed = (1<<cClrBits);
+ }
+ LPBITMAPINFO get() const { return m_pbmiArray; }
+ operator LPBITMAPINFO() const { return m_pbmiArray; }
+ LPBITMAPINFO operator->() const { return m_pbmiArray; }
+
+ private:
+ CBitmapInfoPtr(const CBitmapInfoPtr&); // Disable copy construction
+ CBitmapInfoPtr& operator = (const CBitmapInfoPtr&); // Disable assignment operator
+ LPBITMAPINFO m_pbmiArray;
+ std::vector<byte> m_bmi;
+ };
+
+
+ CBitmap* FromHandle(HBITMAP hBitmap);
+ CBrush* FromHandle(HBRUSH hBrush);
+ CFont* FromHandle(HFONT hFont);
+ CPalette* FromHandle(HPALETTE hPalette);
+ CPen* FromHandle(HPEN hPen);
+ CRgn* FromHandle(HRGN hRgn);
+
+}
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+namespace Win32xx
+{
+
+ ///////////////////////////////////////////////
+ // Declarations for the CGDIObject class
+ //
+
+ inline CGDIObject::CGDIObject()
+ // Constructs the CGDIObject
+ {
+ m_pData = new DataMembers;
+ m_pData->hGDIObject = 0;
+ m_pData->Count = 1L;
+ m_pData->bRemoveObject = TRUE;
+ }
+
+ inline CGDIObject::CGDIObject(const CGDIObject& rhs)
+ // Note: A copy of a CGDIObject is a clone of the original.
+ // Both objects manipulate the one HGDIOBJ.
+ {
+ m_pData = rhs.m_pData;
+ InterlockedIncrement(&m_pData->Count);
+ }
+
+ inline CGDIObject::~CGDIObject()
+ // Deconstructs the CGDIObject
+ {
+ Release();
+ }
+
+ inline CGDIObject& CGDIObject::operator = ( const CGDIObject& rhs )
+ // Note: A copy of a CGDIObject is a clone of the original.
+ // Both objects manipulate the one HGDIOBJ.
+ {
+ if (this != &rhs)
+ {
+ InterlockedIncrement(&rhs.m_pData->Count);
+ Release();
+ m_pData = rhs.m_pData;
+ }
+
+ return *this;
+ }
+
+ inline void CGDIObject::operator = (HGDIOBJ hObject)
+ {
+ assert(m_pData);
+ assert (m_pData->hGDIObject == NULL);
+ m_pData->hGDIObject = hObject;
+ }
+
+ inline void CGDIObject::AddToMap()
+ // Store the HDC and CDC pointer in the HDC map
+ {
+ assert( GetApp() );
+ GetApp()->m_csMapLock.Lock();
+
+ assert(m_pData->hGDIObject);
+ assert(!GetApp()->GetCGDIObjectFromMap(m_pData->hGDIObject));
+
+ GetApp()->m_mapGDI.insert(std::make_pair(m_pData->hGDIObject, this));
+ GetApp()->m_csMapLock.Release();
+ }
+
+ inline void CGDIObject::Attach(HGDIOBJ hObject)
+ // Attaches a GDI HANDLE to the CGDIObject.
+ // The HGDIOBJ will be automatically deleted when the destructor is called unless it is detached.
+ {
+ assert(m_pData);
+
+ if (m_pData->hGDIObject != NULL && m_pData->hGDIObject != hObject)
+ {
+ ::DeleteObject(Detach());
+ }
+
+ CGDIObject* pObject = GetApp()->GetCGDIObjectFromMap(hObject);
+ if (pObject)
+ {
+ delete m_pData;
+ m_pData = pObject->m_pData;
+ InterlockedIncrement(&m_pData->Count);
+ }
+ else
+ {
+ m_pData->hGDIObject = hObject;
+ AddToMap();
+ }
+ }
+
+ inline HGDIOBJ CGDIObject::Detach()
+ // Detaches the HGDIOBJ from this object.
+ {
+ assert(m_pData);
+ assert(m_pData->hGDIObject);
+
+ GetApp()->m_csMapLock.Lock();
+ RemoveFromMap();
+ HGDIOBJ hObject = m_pData->hGDIObject;
+ m_pData->hGDIObject = 0;
+
+ if (m_pData->Count)
+ {
+ if (InterlockedDecrement(&m_pData->Count) == 0)
+ {
+ delete m_pData;
+ }
+ }
+
+ GetApp()->m_csMapLock.Release();
+
+ // Assign values to our data members
+ m_pData = new DataMembers;
+ m_pData->hGDIObject = 0;
+ m_pData->Count = 1L;
+ m_pData->bRemoveObject = TRUE;
+
+ return hObject;
+ }
+
+ inline HGDIOBJ CGDIObject::GetHandle() const
+ {
+ assert(m_pData);
+ return m_pData->hGDIObject;
+ }
+
+ inline int CGDIObject::GetObject(int nCount, LPVOID pObject) const
+ {
+ assert(m_pData);
+ return ::GetObject(m_pData->hGDIObject, nCount, pObject);
+ }
+
+ inline void CGDIObject::Release()
+ {
+ assert(m_pData);
+ BOOL bSucceeded = TRUE;
+
+ if (InterlockedDecrement(&m_pData->Count) == 0)
+ {
+ if (m_pData->hGDIObject != NULL)
+ {
+ if (m_pData->bRemoveObject)
+ bSucceeded = ::DeleteObject(m_pData->hGDIObject);
+ else
+ bSucceeded = TRUE;
+ }
+
+ RemoveFromMap();
+ delete m_pData;
+ m_pData = 0;
+ }
+
+ assert(bSucceeded);
+ }
+
+ inline BOOL CGDIObject::RemoveFromMap()
+ {
+ BOOL Success = FALSE;
+
+ if( GetApp() )
+ {
+ // Allocate an iterator for our HDC map
+ std::map<HGDIOBJ, CGDIObject*, CompareGDI>::iterator m;
+
+ CWinApp* pApp = GetApp();
+ if (pApp)
+ {
+ // Erase the CGDIObject pointer entry from the map
+ pApp->m_csMapLock.Lock();
+ m = pApp->m_mapGDI.find(m_pData->hGDIObject);
+ if (m != pApp->m_mapGDI.end())
+ {
+ pApp->m_mapGDI.erase(m);
+ Success = TRUE;
+ }
+
+ pApp->m_csMapLock.Release();
+ }
+ }
+
+ return Success;
+ }
+
+
+ ///////////////////////////////////////////////
+ // Declarations for the CBitmap class
+ //
+ inline CBitmap::CBitmap()
+ {
+ }
+
+ inline CBitmap::CBitmap(HBITMAP hBitmap)
+ {
+ assert(m_pData);
+ Attach(hBitmap);
+ }
+
+ inline CBitmap::CBitmap(LPCTSTR lpszName)
+ {
+ LoadBitmap(lpszName);
+ }
+
+ inline CBitmap::CBitmap(int nID)
+ {
+ LoadBitmap(nID);
+ }
+
+ inline CBitmap::operator HBITMAP() const
+ {
+ assert(m_pData);
+ return (HBITMAP)m_pData->hGDIObject;
+ }
+
+ inline CBitmap::~CBitmap()
+ {
+ }
+
+ inline BOOL CBitmap::LoadBitmap(int nID)
+ // Loads a bitmap from a resource using the resource ID.
+ {
+ return LoadBitmap(MAKEINTRESOURCE(nID));
+ }
+
+ inline BOOL CBitmap::LoadBitmap(LPCTSTR lpszName)
+ // Loads a bitmap from a resource using the resource string.
+ {
+ assert(GetApp());
+ assert(m_pData);
+
+ HBITMAP hBitmap = (HBITMAP)::LoadImage(GetApp()->GetResourceHandle(), lpszName, IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR);
+ if (hBitmap)
+ {
+ Attach(hBitmap);
+ }
+ return (0 != hBitmap); // boolean expression
+ }
+
+ inline BOOL CBitmap::LoadImage(UINT nID, int cxDesired, int cyDesired, UINT fuLoad)
+ // Loads a bitmap from a resource using the resource ID.
+ {
+ return LoadImage(MAKEINTRESOURCE(nID), cxDesired, cyDesired, fuLoad);
+ }
+
+ inline BOOL CBitmap::LoadImage(LPCTSTR lpszName, int cxDesired, int cyDesired, UINT fuLoad)
+ // Loads a bitmap from a resource using the resource string.
+ {
+ assert(GetApp());
+ assert(m_pData);
+
+ HBITMAP hBitmap = (HBITMAP)::LoadImage(GetApp()->GetResourceHandle(), lpszName, IMAGE_BITMAP, cxDesired, cyDesired, fuLoad);
+ if (hBitmap)
+ {
+ Attach(hBitmap);
+ }
+ return (0 != hBitmap); // boolean expression
+ }
+
+ inline BOOL CBitmap::LoadOEMBitmap(UINT nIDBitmap) // for OBM_/OCR_/OIC_
+ // Loads a predefined bitmap
+ // Predefined bitmaps include: OBM_BTNCORNERS, OBM_BTSIZE, OBM_CHECK, OBM_CHECKBOXES, OBM_CLOSE, OBM_COMBO
+ // OBM_DNARROW, OBM_DNARROWD, OBM_DNARROWI, OBM_LFARROW, OBM_LFARROWD, OBM_LFARROWI, OBM_MNARROW,OBM_OLD_CLOSE
+ // OBM_OLD_DNARROW, OBM_OLD_LFARROW, OBM_OLD_REDUCE, OBM_OLD_RESTORE, OBM_OLD_RGARROW, OBM_OLD_UPARROW
+ // OBM_OLD_ZOOM, OBM_REDUCE, OBM_REDUCED, OBM_RESTORE, OBM_RESTORED, OBM_RGARROW, OBM_RGARROWD, OBM_RGARROWI
+ // OBM_SIZE, OBM_UPARROW, OBM_UPARROWD, OBM_UPARROWI, OBM_ZOOM, OBM_ZOOMD
+ {
+ assert(m_pData);
+
+ HBITMAP hBitmap = ::LoadBitmap(NULL, MAKEINTRESOURCE(nIDBitmap));
+ if (hBitmap)
+ {
+ Attach( ::LoadBitmap(NULL, MAKEINTRESOURCE(nIDBitmap)) );
+ }
+ return (0 != hBitmap); // boolean expression
+ }
+
+#ifndef _WIN32_WCE
+ inline HBITMAP CBitmap::CreateMappedBitmap(UINT nIDBitmap, UINT nFlags /*= 0*/, LPCOLORMAP lpColorMap /*= NULL*/, int nMapSize /*= 0*/)
+ // Creates a new bitmap using the bitmap data and colors specified by the bitmap resource and the color mapping information.
+ {
+ assert(GetApp());
+ assert(m_pData);
+ HBITMAP hBitmap = ::CreateMappedBitmap(GetApp()->GetResourceHandle(), nIDBitmap, (WORD)nFlags, lpColorMap, nMapSize);
+ Attach(hBitmap);
+ return hBitmap;
+ }
+#endif // !_WIN32_WCE
+
+ inline HBITMAP CBitmap::CreateBitmap(int nWidth, int nHeight, UINT nPlanes, UINT nBitsPerPixel, LPCVOID lpBits)
+ // Creates a bitmap with the specified width, height, and color format (color planes and bits-per-pixel).
+ {
+ assert(m_pData);
+ HBITMAP hBitmap = ::CreateBitmap(nWidth, nHeight, nPlanes, nBitsPerPixel, lpBits);
+ Attach(hBitmap);
+ return hBitmap;
+ }
+
+#ifndef _WIN32_WCE
+ inline HBITMAP CBitmap::CreateBitmapIndirect(LPBITMAP lpBitmap)
+ // Creates a bitmap with the width, height, and color format specified in the BITMAP structure.
+ {
+ assert(m_pData);
+ HBITMAP hBitmap = ::CreateBitmapIndirect(lpBitmap);
+ Attach(hBitmap);
+ return hBitmap;
+ }
+#endif // !_WIN32_WCE
+
+ inline HBITMAP CBitmap::CreateCompatibleBitmap(CDC* pDC, int nWidth, int nHeight)
+ // Creates a bitmap compatible with the device that is associated with the specified device context.
+ {
+ assert(m_pData);
+ assert(pDC);
+ HBITMAP hBitmap = ::CreateCompatibleBitmap(pDC->GetHDC(), nWidth, nHeight);
+ Attach(hBitmap);
+ return hBitmap;
+ }
+
+ // Attributes
+ inline BITMAP CBitmap::GetBitmapData() const
+ // Retrieves the BITMAP structure
+ {
+ assert(m_pData);
+ assert(m_pData->hGDIObject != NULL);
+ BITMAP bmp = {0};
+ ::GetObject(m_pData->hGDIObject, sizeof(BITMAP), &bmp);
+ return bmp;
+ }
+
+#ifndef _WIN32_WCE
+ inline CSize CBitmap::GetBitmapDimensionEx() const
+ // Retrieves the dimensions of a compatible bitmap.
+ // The retrieved dimensions must have been set by the SetBitmapDimensionEx function.
+ {
+ assert(m_pData);
+ assert(m_pData->hGDIObject != NULL);
+ CSize Size;
+ ::GetBitmapDimensionEx((HBITMAP)m_pData->hGDIObject, &Size);
+ return Size;
+ }
+
+ inline CSize CBitmap::SetBitmapDimensionEx(int nWidth, int nHeight)
+ // The SetBitmapDimensionEx function assigns preferred dimensions to a bitmap.
+ // These dimensions can be used by applications; however, they are not used by the system.
+ {
+ assert(m_pData);
+ assert(m_pData->hGDIObject != NULL);
+ CSize Size;
+ ::SetBitmapDimensionEx((HBITMAP)m_pData->hGDIObject, nWidth, nHeight, Size);
+ return Size;
+ }
+
+ // DIB support
+ inline HBITMAP CBitmap::CreateDIBitmap(CDC* pDC, CONST BITMAPINFOHEADER* lpbmih, DWORD dwInit, CONST VOID* lpbInit, CONST BITMAPINFO* lpbmi, UINT uColorUse)
+ // Creates a compatible bitmap (DDB) from a DIB and, optionally, sets the bitmap bits.
+ {
+ assert(m_pData);
+ assert(pDC);
+ HBITMAP hBitmap = ::CreateDIBitmap(pDC->GetHDC(), lpbmih, dwInit, lpbInit, lpbmi, uColorUse);
+ Attach(hBitmap);
+ return hBitmap;
+ }
+#endif // !_WIN32_WCE
+
+ inline HBITMAP CBitmap::CreateDIBSection(CDC* pDC, CONST BITMAPINFO* lpbmi, UINT uColorUse, VOID** ppvBits, HANDLE hSection, DWORD dwOffset)
+ // Creates a DIB that applications can write to directly. The function gives you a pointer to the location of the bitmap bit values.
+ // You can supply a handle to a file-mapping object that the function will use to create the bitmap, or you can let the system allocate the memory for the bitmap.
+ {
+ assert(m_pData);
+ assert(pDC);
+ HBITMAP hBitmap = ::CreateDIBSection(pDC->GetHDC(), lpbmi, uColorUse, ppvBits, hSection, dwOffset);
+ Attach(hBitmap);
+ return hBitmap;
+ }
+
+#ifndef _WIN32_WCE
+ inline int CBitmap::GetDIBits(CDC* pDC, UINT uStartScan, UINT cScanLines, LPVOID lpvBits, LPBITMAPINFO lpbmi, UINT uColorUse) const
+ // Retrieves the bits of the specified compatible bitmap and copies them into a buffer as a DIB using the specified format.
+ {
+ assert(m_pData);
+ assert(pDC);
+ assert(m_pData->hGDIObject != NULL);
+ return ::GetDIBits(pDC->GetHDC(), (HBITMAP)m_pData->hGDIObject, uStartScan, cScanLines, lpvBits, lpbmi, uColorUse);
+ }
+
+ inline int CBitmap::SetDIBits(CDC* pDC, UINT uStartScan, UINT cScanLines, CONST VOID* lpvBits, CONST BITMAPINFO* lpbmi, UINT uColorUse)
+ // Sets the pixels in a compatible bitmap (DDB) using the color data found in the specified DIB.
+ {
+ assert(m_pData);
+ assert(pDC);
+ assert(m_pData->hGDIObject != NULL);
+ return ::SetDIBits(pDC->GetHDC(), (HBITMAP)m_pData->hGDIObject, uStartScan, cScanLines, lpvBits, lpbmi, uColorUse);
+ }
+#endif // !_WIN32_WCE
+
+
+ ///////////////////////////////////////////////
+ // Definitions of the CBrush class
+ //
+ inline CBrush::CBrush()
+ {
+ }
+
+ inline CBrush::CBrush(HBRUSH hBrush)
+ {
+ assert(m_pData);
+ Attach(hBrush);
+ }
+
+ inline CBrush::CBrush(COLORREF crColor)
+ {
+ Attach( ::CreateSolidBrush(crColor) );
+ assert (m_pData->hGDIObject);
+ }
+
+ inline CBrush::operator HBRUSH() const
+ {
+ assert(m_pData);
+ return (HBRUSH)m_pData->hGDIObject;
+ }
+
+ inline CBrush::~CBrush()
+ {
+ }
+
+ inline HBRUSH CBrush::CreateSolidBrush(COLORREF crColor)
+ // Creates a logical brush that has the specified solid color.
+ {
+ assert(m_pData);
+ HBRUSH hBrush = ::CreateSolidBrush(crColor);
+ Attach(hBrush);
+ return hBrush;
+ }
+
+#ifndef _WIN32_WCE
+ inline HBRUSH CBrush::CreateHatchBrush(int nIndex, COLORREF crColor)
+ // Creates a logical brush that has the specified hatch pattern and color.
+ {
+ assert(m_pData);
+ HBRUSH hBrush = ::CreateHatchBrush(nIndex, crColor);
+ Attach(hBrush);
+ return hBrush;
+ }
+
+ inline HBRUSH CBrush::CreateBrushIndirect(LPLOGBRUSH lpLogBrush)
+ // Creates a logical brush from style, color, and pattern specified in the LOGPRUSH struct.
+ {
+ assert(m_pData);
+ HBRUSH hBrush = ::CreateBrushIndirect(lpLogBrush);
+ Attach(hBrush);
+ return hBrush;
+ }
+
+ inline HBRUSH CBrush::CreateDIBPatternBrush(HGLOBAL hglbDIBPacked, UINT fuColorSpec)
+ // Creates a logical brush that has the pattern specified by the specified device-independent bitmap (DIB).
+ {
+ assert(m_pData);
+ HBRUSH hBrush = ::CreateDIBPatternBrush(hglbDIBPacked, fuColorSpec);
+ Attach(hBrush);
+ return hBrush;
+ }
+
+ inline HBRUSH CBrush::CreateDIBPatternBrushPt(LPCVOID lpPackedDIB, UINT nUsage)
+ // Creates a logical brush that has the pattern specified by the device-independent bitmap (DIB).
+ {
+ assert(m_pData);
+ HBRUSH hBrush = ::CreateDIBPatternBrushPt(lpPackedDIB, nUsage);
+ Attach(hBrush);
+ return hBrush;
+ }
+
+#endif // !defined(_WIN32_WCE)
+
+ inline HBRUSH CBrush::CreatePatternBrush(CBitmap* pBitmap)
+ // Creates a logical brush with the specified bitmap pattern. The bitmap can be a DIB section bitmap,
+ // which is created by the CreateDIBSection function, or it can be a device-dependent bitmap.
+ {
+ assert(m_pData);
+ assert(pBitmap);
+ HBRUSH hBrush = ::CreatePatternBrush(*pBitmap);
+ Attach(hBrush);
+ return hBrush;
+ }
+
+ inline LOGBRUSH CBrush::GetLogBrush() const
+ // Retrieves the LOGBRUSH structure that defines the style, color, and pattern of a physical brush.
+ {
+ assert(m_pData);
+ assert(m_pData->hGDIObject != NULL);
+ LOGBRUSH LogBrush = {0};
+ ::GetObject (m_pData->hGDIObject, sizeof(LOGBRUSH), &LogBrush);
+ return LogBrush;
+ }
+
+
+ ///////////////////////////////////////////////
+ // Definitions of the CFont class
+ //
+ inline CFont::CFont()
+ {
+ }
+
+ inline CFont::CFont(HFONT hFont)
+ {
+ assert(m_pData);
+ Attach(hFont);
+ }
+
+ inline CFont::CFont(const LOGFONT* lpLogFont)
+ {
+ assert(m_pData);
+ Attach( ::CreateFontIndirect(lpLogFont) );
+ }
+
+ inline CFont::operator HFONT() const
+ {
+ assert(m_pData);
+ return (HFONT)m_pData->hGDIObject;
+ }
+
+ inline CFont::~CFont()
+ {
+ }
+
+ inline HFONT CFont::CreateFontIndirect(const LOGFONT* lpLogFont)
+ // Creates a logical font that has the specified characteristics.
+ {
+ assert(m_pData);
+ HFONT hFont = ::CreateFontIndirect(lpLogFont);
+ Attach(hFont);
+ return hFont;
+ }
+
+ inline HFONT CFont::CreatePointFont(int nPointSize, LPCTSTR lpszFaceName, CDC* pDC /*= NULL*/, BOOL bBold /*= FALSE*/, BOOL bItalic /*= FALSE*/)
+ // Creates a font of a specified typeface and point size.
+ {
+ LOGFONT logFont = { 0 };
+ logFont.lfCharSet = DEFAULT_CHARSET;
+ logFont.lfHeight = nPointSize;
+
+ lstrcpy(logFont.lfFaceName, lpszFaceName);
+
+ if (bBold)
+ logFont.lfWeight = FW_BOLD;
+ if (bItalic)
+ logFont.lfItalic = (BYTE)TRUE;
+
+ return CreatePointFontIndirect(&logFont, pDC);
+ }
+
+ inline HFONT CFont::CreatePointFontIndirect(const LOGFONT* lpLogFont, CDC* pDC /* = NULL*/)
+ // Creates a font of a specified typeface and point size.
+ // This function automatically converts the height in lfHeight to logical units using the specified device context.
+ {
+ HDC hDC = pDC? pDC->GetHDC() : NULL;
+ HDC hDC1 = (hDC != NULL) ? hDC : ::GetDC(HWND_DESKTOP);
+
+ // convert nPointSize to logical units based on hDC
+ LOGFONT logFont = *lpLogFont;
+
+#ifndef _WIN32_WCE
+ POINT pt = { 0, 0 };
+ pt.y = ::MulDiv(::GetDeviceCaps(hDC1, LOGPIXELSY), logFont.lfHeight, 720); // 72 points/inch, 10 decipoints/point
+ ::DPtoLP(hDC1, &pt, 1);
+
+ POINT ptOrg = { 0, 0 };
+ ::DPtoLP(hDC1, &ptOrg, 1);
+
+ logFont.lfHeight = -abs(pt.y - ptOrg.y);
+#else // CE specific
+ // DP and LP are always the same on CE
+ logFont.lfHeight = -abs(((::GetDeviceCaps(hDC1, LOGPIXELSY)* logFont.lfHeight)/ 720));
+#endif // _WIN32_WCE
+
+ if (hDC == NULL)
+ ::ReleaseDC (NULL, hDC1);
+
+ return CreateFontIndirect (&logFont);
+ }
+
+#ifndef _WIN32_WCE
+
+ inline HFONT CFont::CreateFont(int nHeight, int nWidth, int nEscapement,
+ int nOrientation, int nWeight, DWORD dwItalic, DWORD dwUnderline,
+ DWORD dwStrikeOut, DWORD dwCharSet, DWORD dwOutPrecision,
+ DWORD dwClipPrecision, DWORD dwQuality, DWORD dwPitchAndFamily,
+ LPCTSTR lpszFacename)
+ // Creates a logical font with the specified characteristics.
+ {
+ HFONT hFont = ::CreateFont(nHeight, nWidth, nEscapement,
+ nOrientation, nWeight, dwItalic, dwUnderline, dwStrikeOut,
+ dwCharSet, dwOutPrecision, dwClipPrecision, dwQuality,
+ dwPitchAndFamily, lpszFacename);
+
+ Attach(hFont);
+ return hFont;
+ }
+#endif // #ifndef _WIN32_WCE
+
+ inline LOGFONT CFont::GetLogFont() const
+ // Retrieves the Logfont structure that contains font attributes.
+ {
+ assert(m_pData);
+ assert(m_pData->hGDIObject != NULL);
+ LOGFONT LogFont = {0};
+ ::GetObject(m_pData->hGDIObject, sizeof(LOGFONT), &LogFont);
+ return LogFont;
+ }
+
+
+ ///////////////////////////////////////////////
+ // Definitions of the CPalette class
+ //
+ inline CPalette::CPalette()
+ {
+ }
+
+ inline CPalette::CPalette(HPALETTE hPalette)
+ {
+ Attach(hPalette);
+ }
+
+ inline CPalette::operator HPALETTE() const
+ {
+ assert(m_pData);
+ return (HPALETTE)m_pData->hGDIObject;
+ }
+
+ inline CPalette::~CPalette ()
+ {
+ }
+
+ inline HPALETTE CPalette::CreatePalette(LPLOGPALETTE lpLogPalette)
+ // Creates a logical palette from the information in the specified LOGPALETTE structure.
+ {
+ assert(m_pData);
+ HPALETTE hPalette = ::CreatePalette (lpLogPalette);
+ Attach(hPalette);
+ return hPalette;
+ }
+
+#ifndef _WIN32_WCE
+ inline HPALETTE CPalette::CreateHalftonePalette(CDC* pDC)
+ // Creates a halftone palette for the specified device context (DC).
+ {
+ assert(m_pData);
+ assert(pDC);
+ HPALETTE hPalette = ::CreateHalftonePalette(pDC->GetHDC());
+ Attach(hPalette);
+ return hPalette;
+ }
+#endif // !_WIN32_WCE
+
+ inline int CPalette::GetEntryCount() const
+ // Retrieve the number of entries in the palette.
+ {
+ assert(m_pData);
+ assert(m_pData->hGDIObject != NULL);
+ WORD nEntries = 0;
+ ::GetObject(m_pData->hGDIObject, sizeof(WORD), &nEntries);
+ return (int)nEntries;
+ }
+
+ inline UINT CPalette::GetPaletteEntries(UINT nStartIndex, UINT nNumEntries, LPPALETTEENTRY lpPaletteColors) const
+ // Retrieves a specified range of palette entries from the palette.
+ {
+ assert(m_pData);
+ assert(m_pData->hGDIObject != NULL);
+ return ::GetPaletteEntries((HPALETTE)m_pData->hGDIObject, nStartIndex, nNumEntries, lpPaletteColors);
+ }
+
+ inline UINT CPalette::SetPaletteEntries(UINT nStartIndex, UINT nNumEntries, LPPALETTEENTRY lpPaletteColors)
+ // Sets RGB (red, green, blue) color values and flags in a range of entries in the palette.
+ {
+ assert(m_pData);
+ assert(m_pData->hGDIObject != NULL);
+ return ::SetPaletteEntries((HPALETTE)m_pData->hGDIObject, nStartIndex, nNumEntries, lpPaletteColors);
+ }
+
+#ifndef _WIN32_WCE
+ inline void CPalette::AnimatePalette(UINT nStartIndex, UINT nNumEntries, LPPALETTEENTRY lpPaletteColors)
+ // Replaces entries in the palette.
+ {
+ assert(m_pData);
+ assert(m_pData->hGDIObject != NULL);
+ ::AnimatePalette((HPALETTE)m_pData->hGDIObject, nStartIndex, nNumEntries, lpPaletteColors);
+ }
+
+ inline BOOL CPalette::ResizePalette(UINT nNumEntries)
+ // Increases or decreases the size of the palette based on the specified value.
+ {
+ assert(m_pData);
+ assert(m_pData->hGDIObject != NULL);
+ return ::ResizePalette((HPALETTE)m_pData->hGDIObject, nNumEntries);
+ }
+#endif // !_WIN32_WCE
+
+ inline UINT CPalette::GetNearestPaletteIndex(COLORREF crColor) const
+ // Retrieves the index for the entry in the palette most closely matching a specified color value.
+ {
+ assert(m_pData);
+ assert(m_pData->hGDIObject != NULL);
+ return ::GetNearestPaletteIndex((HPALETTE)m_pData->hGDIObject, crColor);
+ }
+
+
+ ///////////////////////////////////////////////
+ // Declarations for the CPen class
+ //
+ inline CPen::CPen()
+ {
+ }
+
+ inline CPen::CPen(HPEN hPen)
+ {
+ Attach(hPen);
+ }
+
+ inline CPen::CPen(int nPenStyle, int nWidth, COLORREF crColor)
+ {
+ assert(m_pData);
+ Attach( ::CreatePen(nPenStyle, nWidth, crColor) );
+ }
+
+#ifndef _WIN32_WCE
+ inline CPen::CPen(int nPenStyle, int nWidth, const LOGBRUSH* pLogBrush, int nStyleCount /*= 0*/, const DWORD* lpStyle /*= NULL*/)
+ {
+ assert(m_pData);
+ Attach( ::ExtCreatePen(nPenStyle, nWidth, pLogBrush, nStyleCount, lpStyle) );
+ }
+#endif // !_WIN32_WCE
+
+ inline CPen::operator HPEN () const
+ {
+ assert(m_pData);
+ return (HPEN)m_pData->hGDIObject;
+ }
+
+ inline CPen::~CPen()
+ {
+ }
+
+ inline HPEN CPen::CreatePen(int nPenStyle, int nWidth, COLORREF crColor)
+ // Creates a logical pen that has the specified style, width, and color.
+ {
+ assert(m_pData);
+ HPEN hPen = ::CreatePen(nPenStyle, nWidth, crColor);
+ Attach(hPen);
+ return hPen;
+ }
+
+ inline HPEN CPen::CreatePenIndirect(LPLOGPEN lpLogPen)
+ // Creates a logical cosmetic pen that has the style, width, and color specified in a structure.
+ {
+ assert(m_pData);
+ HPEN hPen = ::CreatePenIndirect(lpLogPen);
+ Attach(hPen);
+ return hPen;
+ }
+
+ inline LOGPEN CPen::GetLogPen() const
+ {
+ // Retrieves the LOGPEN struct that specifies the pen's style, width, and color.
+ assert(m_pData);
+ assert(m_pData->hGDIObject != NULL);
+
+ LOGPEN LogPen = {0};
+ ::GetObject(m_pData->hGDIObject, sizeof(LOGPEN), &LogPen);
+ return LogPen;
+ }
+
+#ifndef _WIN32_WCE
+ inline HPEN CPen::ExtCreatePen(int nPenStyle, int nWidth, const LOGBRUSH* pLogBrush, int nStyleCount /* = 0*/, const DWORD* lpStyle /*= NULL*/)
+ // Creates a logical cosmetic or geometric pen that has the specified style, width, and brush attributes.
+ {
+ assert(m_pData);
+ HPEN hPen = ::ExtCreatePen(nPenStyle, nWidth, pLogBrush, nStyleCount, lpStyle);
+ Attach(hPen);
+ return hPen;
+ }
+
+ inline EXTLOGPEN CPen::GetExtLogPen() const
+ // Retrieves the EXTLOGPEN struct that specifies the pen's style, width, color and brush attributes.
+ {
+ assert(m_pData);
+ assert(m_pData->hGDIObject != NULL);
+
+ EXTLOGPEN ExLogPen = {0};
+ ::GetObject(m_pData->hGDIObject, sizeof(EXTLOGPEN), &ExLogPen);
+ return ExLogPen;
+ }
+#endif // !_WIN32_WCE
+
+
+ ///////////////////////////////////////////////
+ // Definitions of the CRgn class
+ //
+ inline CRgn::CRgn()
+ {
+ }
+
+ inline CRgn::CRgn(HRGN hRgn)
+ {
+ assert(m_pData);
+ Attach(hRgn);
+ }
+
+ inline CRgn::operator HRGN() const
+ {
+ assert(m_pData);
+ return (HRGN)m_pData->hGDIObject;
+ }
+
+ inline CRgn::~CRgn()
+ {
+ }
+
+ inline HRGN CRgn::CreateRectRgn(int x1, int y1, int x2, int y2)
+ // Creates a rectangular region.
+ {
+ assert(m_pData);
+ HRGN hRgn = ::CreateRectRgn(x1, y1, x2, y2);
+ Attach(hRgn);
+ return hRgn;
+ }
+
+ inline HRGN CRgn::CreateRectRgnIndirect(const RECT& rc)
+ // Creates a rectangular region.
+ {
+ assert(m_pData);
+ HRGN hRgn = ::CreateRectRgnIndirect(&rc);
+ Attach(hRgn);
+ return hRgn;
+ }
+
+#ifndef _WIN32_WCE
+ inline HRGN CRgn::CreateEllipticRgn(int x1, int y1, int x2, int y2)
+ // Creates an elliptical region.
+ {
+ assert(m_pData);
+ HRGN hRgn = ::CreateEllipticRgn(x1, y1, x2, y2);
+ Attach(hRgn);
+ return hRgn;
+ }
+
+ inline HRGN CRgn::CreateEllipticRgnIndirect(const RECT& rc)
+ // Creates an elliptical region.
+ {
+ assert(m_pData);
+ HRGN hRgn = ::CreateEllipticRgnIndirect(&rc);
+ Attach(hRgn);
+ return hRgn;
+ }
+
+ inline HRGN CRgn::CreatePolygonRgn(LPPOINT lpPoints, int nCount, int nMode)
+ // Creates a polygonal region.
+ {
+ assert(m_pData);
+ HRGN hRgn = ::CreatePolygonRgn(lpPoints, nCount, nMode);
+ Attach(hRgn);
+ return hRgn;
+ }
+
+ inline HRGN CRgn::CreatePolyPolygonRgn(LPPOINT lpPoints, LPINT lpPolyCounts, int nCount, int nPolyFillMode)
+ // Creates a region consisting of a series of polygons. The polygons can overlap.
+ {
+ assert(m_pData);
+ HRGN hRgn = ::CreatePolyPolygonRgn(lpPoints, lpPolyCounts, nCount, nPolyFillMode);
+ Attach(hRgn);
+ return hRgn;
+ }
+
+ inline HRGN CRgn::CreateRoundRectRgn(int x1, int y1, int x2, int y2, int x3, int y3)
+ // Creates a rectangular region with rounded corners.
+ {
+ assert(m_pData);
+ HRGN hRgn = ::CreateRoundRectRgn(x1, y1, x2, y2, x3, y3);
+ Attach(hRgn);
+ return hRgn;
+ }
+
+ inline HRGN CRgn::CreateFromPath(HDC hDC)
+ // Creates a region from the path that is selected into the specified device context.
+ // The resulting region uses device coordinates.
+ {
+ assert(m_pData);
+ assert(hDC != NULL);
+ HRGN hRgn = ::PathToRegion(hDC);
+ Attach(hRgn);
+ return hRgn;
+ }
+
+#endif // !_WIN32_WCE
+
+ inline HRGN CRgn::CreateFromData(const XFORM* lpXForm, int nCount, const RGNDATA* pRgnData)
+ // Creates a region from the specified region and transformation data.
+ {
+ assert(m_pData);
+ HRGN hRgn = ::ExtCreateRegion(lpXForm, nCount, pRgnData);
+ Attach(hRgn);
+ return hRgn;
+ }
+
+ inline void CRgn::SetRectRgn(int x1, int y1, int x2, int y2)
+ // converts the region into a rectangular region with the specified coordinates.
+ {
+ assert(m_pData);
+ assert(m_pData->hGDIObject != NULL);
+ ::SetRectRgn((HRGN)m_pData->hGDIObject, x1, y1, x2, y2);
+ }
+
+ inline void CRgn::SetRectRgn(const RECT& rc)
+ // converts the region into a rectangular region with the specified coordinates.
+ {
+ assert(m_pData);
+ assert(m_pData->hGDIObject != NULL);
+ ::SetRectRgn((HRGN)m_pData->hGDIObject, rc.left, rc.top, rc.right, rc.bottom);
+ }
+
+ inline int CRgn::CombineRgn(CRgn* pRgnSrc1, CRgn* pRgnSrc2, int nCombineMode)
+ // Combines two sepcified regions and stores the result.
+ {
+ assert(m_pData);
+ assert(m_pData->hGDIObject != NULL);
+ assert(pRgnSrc1);
+ assert(pRgnSrc2);
+ return ::CombineRgn((HRGN)m_pData->hGDIObject, *pRgnSrc1, *pRgnSrc2, nCombineMode);
+ }
+
+ inline int CRgn::CombineRgn(CRgn* pRgnSrc, int nCombineMode)
+ // Combines the sepcified region with the current region.
+ {
+ assert(m_pData);
+ assert(m_pData->hGDIObject != NULL);
+ assert(pRgnSrc);
+ return ::CombineRgn((HRGN)m_pData->hGDIObject, (HRGN)m_pData->hGDIObject, *pRgnSrc, nCombineMode);
+ }
+
+ inline int CRgn::CopyRgn(CRgn* pRgnSrc)
+ // Assigns the specified region to the current region.
+ {
+ assert(m_pData);
+ assert(m_pData->hGDIObject == NULL);
+ assert(pRgnSrc);
+ return ::CombineRgn((HRGN)m_pData->hGDIObject, *pRgnSrc, NULL, RGN_COPY);
+ }
+
+ inline BOOL CRgn::EqualRgn(CRgn* pRgn) const
+ // Checks the two specified regions to determine whether they are identical.
+ {
+ assert(m_pData);
+ assert(m_pData->hGDIObject != NULL);
+ assert(pRgn);
+ return ::EqualRgn((HRGN)m_pData->hGDIObject, *pRgn);
+ }
+
+ inline int CRgn::OffsetRgn(int x, int y)
+ // Moves a region by the specified offsets.
+ {
+ assert(m_pData);
+ assert(m_pData->hGDIObject != NULL);
+ return ::OffsetRgn((HRGN)m_pData->hGDIObject, x, y);
+ }
+
+ inline int CRgn::OffsetRgn(POINT& pt)
+ // Moves a region by the specified offsets.
+ {
+ assert(m_pData);
+ assert(m_pData->hGDIObject != NULL);
+ return ::OffsetRgn((HRGN)m_pData->hGDIObject, pt.x, pt.y);
+ }
+
+ inline int CRgn::GetRgnBox(RECT& rc) const
+ // Retrieves the bounding rectangle of the region, and stores it in the specified RECT.
+ // The return value indicates the region's complexity: NULLREGION;SIMPLEREGION; or COMPLEXREGION.
+ {
+ assert(m_pData);
+ assert(m_pData->hGDIObject != NULL);
+ return ::GetRgnBox((HRGN)m_pData->hGDIObject, &rc);
+ }
+
+ inline int CRgn::GetRegionData(LPRGNDATA lpRgnData, int nDataSize) const
+ // Fills the specified buffer with data describing a region.
+ {
+ assert(m_pData);
+ assert(m_pData->hGDIObject != NULL);
+ return (int)::GetRegionData((HRGN)m_pData->hGDIObject, nDataSize, lpRgnData);
+ }
+
+ inline BOOL CRgn::PtInRegion(int x, int y) const
+ // Determines whether the specified point is inside the specified region.
+ {
+ assert(m_pData);
+ assert(m_pData->hGDIObject != NULL);
+ return ::PtInRegion((HRGN)m_pData->hGDIObject, x, y);
+ }
+
+ inline BOOL CRgn::PtInRegion(POINT& pt) const
+ // Determines whether the specified point is inside the specified region.
+ {
+ assert(m_pData);
+ assert(m_pData->hGDIObject != NULL);
+ return ::PtInRegion((HRGN)m_pData->hGDIObject, pt.x, pt.y);
+ }
+
+ inline BOOL CRgn::RectInRegion(const RECT& rc) const
+ // Determines whether the specified rect is inside the specified region.
+ {
+ assert(m_pData);
+ assert(m_pData->hGDIObject != NULL);
+ return ::RectInRegion((HRGN)m_pData->hGDIObject, &rc);
+ }
+
+
+ ///////////////////////////////////////////////
+ // Definitions of the CDC class
+ //
+ inline CDC::CDC()
+ {
+ // Allocate memory for our data members
+ m_pData = new DataMembers;
+
+ // Assign values to our data members
+ m_pData->hDC = 0;
+ m_pData->Count = 1L;
+ m_pData->bRemoveHDC = TRUE;
+ m_pData->hWnd = 0;
+ }
+
+ inline CDC::CDC(HDC hDC, HWND hWnd /*= 0*/)
+ // This constructor assigns an existing HDC to the CDC
+ // The HDC WILL be released or deleted when the CDC object is destroyed
+ // The hWnd paramter is only used in WindowsCE. It specifies the HWND of a Window or
+ // Window Client DC
+
+ // Note: this constructor permits a call like this:
+ // CDC MyCDC = SomeHDC;
+ // or
+ // CDC MyCDC = ::CreateCompatibleDC(SomeHDC);
+ // or
+ // CDC MyCDC = ::GetDC(SomeHWND);
+ {
+ UNREFERENCED_PARAMETER(hWnd);
+ assert(hDC);
+
+ CDC* pDC = GetApp()->GetCDCFromMap(hDC);
+ if (pDC)
+ {
+ m_pData = pDC->m_pData;
+ InterlockedIncrement(&m_pData->Count);
+ }
+ else
+ {
+ // Allocate memory for our data members
+ m_pData = new DataMembers;
+
+ // Assign values to our data members
+ m_pData->hDC = hDC;
+ m_pData->Count = 1L;
+ m_pData->bRemoveHDC = TRUE;
+ m_pData->nSavedDCState = ::SaveDC(hDC);
+#ifndef _WIN32_WCE
+ m_pData->hWnd = ::WindowFromDC(hDC);
+#else
+ m_pData->hWnd = hWnd;
+#endif
+ if (m_pData->hWnd)
+ AddToMap();
+ }
+ }
+
+#ifndef _WIN32_WCE
+ inline void CDC::operator = (const HDC hDC)
+ // Note: this assignment operater permits a call like this:
+ // CDC MyCDC;
+ // MyCDC = SomeHDC;
+ {
+ Attach(hDC);
+ }
+#endif
+
+ inline CDC::CDC(const CDC& rhs) // Copy constructor
+ // The copy constructor is called when a temporary copy of the CDC needs to be created.
+ // This can happen when a CDC is passed by value in a function call. Each CDC copy manages
+ // the same Device Context and GDI objects.
+ {
+ m_pData = rhs.m_pData;
+ InterlockedIncrement(&m_pData->Count);
+ }
+
+ inline CDC& CDC::operator = (const CDC& rhs)
+ // Note: A copy of a CDC is a clone of the original.
+ // Both objects manipulate the one HDC
+ {
+ if (this != &rhs)
+ {
+ InterlockedIncrement(&rhs.m_pData->Count);
+ Release();
+ m_pData = rhs.m_pData;
+ }
+
+ return *this;
+ }
+
+ inline CDC::~CDC ()
+ {
+ Release();
+ }
+
+ inline void CDC::AddToMap()
+ // Store the HDC and CDC pointer in the HDC map
+ {
+ assert( GetApp() );
+ assert(m_pData->hDC);
+ GetApp()->m_csMapLock.Lock();
+
+ assert(m_pData->hDC);
+ assert(!GetApp()->GetCDCFromMap(m_pData->hDC));
+
+ GetApp()->m_mapHDC.insert(std::make_pair(m_pData->hDC, this));
+ GetApp()->m_csMapLock.Release();
+ }
+
+ inline void CDC::Attach(HDC hDC, HWND hWnd /* = 0*/)
+ // Attaches a HDC to the CDC object.
+ // The HDC will be automatically deleted or released when the destructor is called.
+ // The hWnd parameter is only used on WindowsCE. It specifies the HWND of a Window or
+ // Window Client DC
+ {
+ UNREFERENCED_PARAMETER(hWnd);
+ assert(m_pData);
+ assert(0 == m_pData->hDC);
+ assert(hDC);
+
+ CDC* pDC = GetApp()->GetCDCFromMap(hDC);
+ if (pDC)
+ {
+ delete m_pData;
+ m_pData = pDC->m_pData;
+ InterlockedIncrement(&m_pData->Count);
+ }
+ else
+ {
+ m_pData->hDC = hDC;
+
+#ifndef _WIN32_WCE
+ m_pData->hWnd = ::WindowFromDC(hDC);
+#else
+ m_pData->hWnd = hWnd;
+#endif
+
+ if (m_pData->hWnd == 0)
+ AddToMap();
+ m_pData->nSavedDCState = ::SaveDC(hDC);
+ }
+ }
+
+ inline HDC CDC::Detach()
+ // Detaches the HDC from this object.
+ {
+ assert(m_pData);
+ assert(m_pData->hDC);
+
+ GetApp()->m_csMapLock.Lock();
+ RemoveFromMap();
+ HDC hDC = m_pData->hDC;
+ m_pData->hDC = 0;
+
+ if (m_pData->Count)
+ {
+ if (InterlockedDecrement(&m_pData->Count) == 0)
+ {
+ delete m_pData;
+ }
+ }
+
+ GetApp()->m_csMapLock.Release();
+
+ // Assign values to our data members
+ m_pData = new DataMembers;
+ m_pData->hDC = 0;
+ m_pData->Count = 1L;
+ m_pData->bRemoveHDC = TRUE;
+ m_pData->hWnd = 0;
+
+ return hDC;
+ }
+
+ // Initialization
+ inline BOOL CDC::CreateCompatibleDC(CDC* pDC)
+ // Returns a memory device context (DC) compatible with the specified device.
+ {
+ assert(m_pData->hDC == NULL);
+ HDC hdcSource = (pDC == NULL)? NULL : pDC->GetHDC();
+ HDC hDC = ::CreateCompatibleDC(hdcSource);
+ if (hDC)
+ {
+ m_pData->hDC = hDC;
+ AddToMap();
+ }
+ return (hDC != NULL); // boolean expression
+ }
+
+ inline BOOL CDC::CreateDC(LPCTSTR lpszDriver, LPCTSTR lpszDevice, LPCTSTR lpszOutput, const DEVMODE* pInitData)
+ // Returns a device context (DC) for a device using the specified name.
+ {
+ assert(m_pData->hDC == NULL);
+ HDC hDC = ::CreateDC(lpszDriver, lpszDevice, lpszOutput, pInitData);
+ if (hDC)
+ {
+ m_pData->hDC = hDC;
+ AddToMap();
+ }
+ return (hDC != NULL); // boolean expression
+ }
+
+#ifndef _WIN32_WCE
+ inline BOOL CDC::CreateIC(LPCTSTR lpszDriver, LPCTSTR lpszDevice, LPCTSTR lpszOutput, const DEVMODE* pInitData)
+ {
+ assert(m_pData->hDC == NULL);
+ HDC hDC = ::CreateIC(lpszDriver, lpszDevice, lpszOutput, pInitData);
+ if (hDC)
+ {
+ m_pData->hDC = hDC;
+ AddToMap();
+ }
+ return (hDC != NULL); // boolean expression
+ }
+#endif
+
+ inline void CDC::DrawBitmap(int x, int y, int cx, int cy, CBitmap& Bitmap, COLORREF clrMask)
+ // Draws the specified bitmap to the specified DC using the mask colour provided as the transparent colour
+ // Suitable for use with a Window DC or a memory DC
+ {
+ // Create the Image memory DC
+ CMemDC dcImage(this);
+ dcImage.SetBkColor(clrMask);
+ dcImage.SelectObject(&Bitmap);
+
+ // Create the Mask memory DC
+ CMemDC dcMask(this);
+ dcMask.CreateBitmap(cx, cy, 1, 1, NULL);
+ dcMask.BitBlt(0, 0, cx, cy, &dcImage, 0, 0, SRCCOPY);
+
+ // Mask the image to 'this' DC
+ BitBlt(x, y, cx, cy, &dcImage, 0, 0, SRCINVERT);
+ BitBlt(x, y, cx, cy, &dcMask, 0, 0, SRCAND);
+ BitBlt(x, y, cx, cy, &dcImage, 0, 0, SRCINVERT);
+ }
+
+ inline CDC* CDC::AddTempHDC(HDC hDC, HWND hWnd)
+ // Returns the CDC object associated with the device context handle
+ // The HDC is removed when the CDC is destroyed
+ {
+ assert( GetApp() );
+ CDC* pDC = new CDC;
+ pDC->m_pData->hDC = hDC;
+ GetApp()->AddTmpDC(pDC);
+ pDC->m_pData->bRemoveHDC = TRUE;
+ pDC->m_pData->hWnd = hWnd;
+ return pDC;
+ }
+
+ inline void CDC::GradientFill(COLORREF Color1, COLORREF Color2, const RECT& rc, BOOL bVertical)
+ // An efficient color gradient filler compatible with all Windows operating systems
+ {
+ int Width = rc.right - rc.left;
+ int Height = rc.bottom - rc.top;
+
+ int r1 = GetRValue(Color1);
+ int g1 = GetGValue(Color1);
+ int b1 = GetBValue(Color1);
+
+ int r2 = GetRValue(Color2);
+ int g2 = GetGValue(Color2);
+ int b2 = GetBValue(Color2);
+
+ COLORREF OldBkColor = GetBkColor();
+
+ if (bVertical)
+ {
+ for(int i=0; i < Width; ++i)
+ {
+ int r = r1 + (i * (r2-r1) / Width);
+ int g = g1 + (i * (g2-g1) / Width);
+ int b = b1 + (i * (b2-b1) / Width);
+ SetBkColor(RGB(r, g, b));
+ CRect line( i + rc.left, rc.top, i + 1 + rc.left, rc.top+Height);
+ ExtTextOut(0, 0, ETO_OPAQUE, line, NULL, 0, 0);
+ }
+ }
+ else
+ {
+ for(int i=0; i < Height; ++i)
+ {
+ int r = r1 + (i * (r2-r1) / Height);
+ int g = g1 + (i * (g2-g1) / Height);
+ int b = b1 + (i * (b2-b1) / Height);
+ SetBkColor(RGB(r, g, b));
+ CRect line(rc.left, i + rc.top, rc.left+Width, i + 1 + rc.top);
+ ExtTextOut(0, 0, ETO_OPAQUE, line, NULL, 0, 0);
+ }
+ }
+
+ SetBkColor(OldBkColor);
+ }
+
+ inline void CDC::Release()
+ {
+ GetApp()->m_csMapLock.Lock();
+
+ if (m_pData->Count)
+ {
+ if (InterlockedDecrement(&m_pData->Count) == 0)
+ {
+ Destroy();
+ delete m_pData;
+ m_pData = 0;
+ }
+ }
+
+ GetApp()->m_csMapLock.Release();
+ }
+
+ inline BOOL CDC::RemoveFromMap()
+ {
+ BOOL Success = FALSE;
+
+ if( GetApp() )
+ {
+ // Allocate an iterator for our HDC map
+ std::map<HDC, CDC*, CompareHDC>::iterator m;
+
+ CWinApp* pApp = GetApp();
+ if (pApp)
+ {
+ // Erase the CDC pointer entry from the map
+ pApp->m_csMapLock.Lock();
+ m = pApp->m_mapHDC.find(m_pData->hDC);
+ if (m != pApp->m_mapHDC.end())
+ {
+ pApp->m_mapHDC.erase(m);
+ Success = TRUE;
+ }
+
+ pApp->m_csMapLock.Release();
+ }
+ }
+ return Success;
+ }
+
+ inline void CDC::SolidFill(COLORREF Color, const RECT& rc)
+ // Fills a rectangle with a solid color
+ {
+ COLORREF OldColor = SetBkColor(Color);
+ ExtTextOut(0, 0, ETO_OPAQUE, &rc, NULL, 0, 0);
+ SetBkColor(OldColor);
+ }
+
+ // Bitmap functions
+ inline CBitmap* CDC::CreateCompatibleBitmap(CDC* pDC, int cx, int cy)
+ // Creates a compatible bitmap and selects it into the device context.
+ {
+ assert(m_pData->hDC);
+ assert(pDC);
+
+ CBitmap* pBitmap = new CBitmap;
+ pBitmap->CreateCompatibleBitmap(pDC, cx, cy);
+ m_pData->m_vGDIObjects.push_back(pBitmap);
+ return SelectObject(pBitmap);
+ }
+
+ inline CBitmap* CDC::CreateBitmap(int cx, int cy, UINT Planes, UINT BitsPerPixel, LPCVOID pvColors)
+ // Creates a bitmap and selects it into the device context.
+ // Returns a pointer to the old bitmap selected out of the device context
+ {
+ assert(m_pData->hDC);
+
+ CBitmap* pBitmap = new CBitmap;
+ pBitmap->CreateBitmap(cx, cy, Planes, BitsPerPixel, pvColors);
+ m_pData->m_vGDIObjects.push_back(pBitmap);
+ return SelectObject(pBitmap);
+ }
+
+#ifndef _WIN32_WCE
+ inline CBitmap* CDC::CreateBitmapIndirect (LPBITMAP lpBitmap)
+ // Creates a bitmap and selects it into the device context.
+ // Returns a pointer to the old bitmap selected out of the device context
+ {
+ assert(m_pData->hDC);
+
+ CBitmap* pBitmap = new CBitmap;
+ pBitmap->CreateBitmapIndirect(lpBitmap);
+ m_pData->m_vGDIObjects.push_back(pBitmap);
+ return SelectObject(pBitmap);
+ }
+
+ inline CBitmap* CDC::CreateDIBitmap(CDC* pDC, const BITMAPINFOHEADER& bmih, DWORD fdwInit, LPCVOID lpbInit,
+ BITMAPINFO& bmi, UINT fuUsage)
+ // Creates a bitmap and selects it into the device context.
+ // Returns a pointer to the old bitmap selected out of the device context
+ {
+ assert(m_pData->hDC);
+ assert(pDC);
+
+ CBitmap* pBitmap = new CBitmap;
+ pBitmap->CreateDIBitmap(pDC, &bmih, fdwInit, lpbInit, &bmi, fuUsage);
+ m_pData->m_vGDIObjects.push_back(pBitmap);
+ return SelectObject(pBitmap);
+ }
+#endif
+
+ inline CBitmap* CDC::CreateDIBSection(CDC* pDC, const BITMAPINFO& bmi, UINT iUsage, LPVOID *ppvBits,
+ HANDLE hSection, DWORD dwOffset)
+ // Creates a bitmap and selects it into the device context.
+ // Returns a pointer to the old bitmap selected out of the device context
+ {
+ assert(m_pData->hDC);
+ assert(pDC);
+
+ CBitmap* pBitmap = new CBitmap;
+ pBitmap->CreateDIBSection(pDC, &bmi, iUsage, ppvBits, hSection, dwOffset);
+ m_pData->m_vGDIObjects.push_back(pBitmap);
+ return SelectObject(pBitmap);
+ }
+
+ inline void CDC::Destroy()
+ // Deletes or releases the device context and returns the CDC object to its
+ // default state, ready for reuse.
+ {
+ if (m_pData->hDC)
+ {
+ RemoveFromMap();
+ if (m_pData->bRemoveHDC)
+ {
+ // Return the DC back to its initial state
+ ::RestoreDC(m_pData->hDC, m_pData->nSavedDCState);
+
+ // We need to release a Window DC, and delete a memory DC
+ if (m_pData->hWnd)
+ ::ReleaseDC(m_pData->hWnd, m_pData->hDC);
+ else
+ if (!::DeleteDC(m_pData->hDC))
+ ::ReleaseDC(NULL, m_pData->hDC);
+
+ m_pData->hDC = 0;
+ m_pData->hWnd = 0;
+ m_pData->bRemoveHDC = TRUE;
+ }
+ }
+
+ // RemoveFromMap();
+ }
+
+ inline BITMAP CDC::GetBitmapData() const
+ // Retrieves the BITMAP information for the current HBITMAP.
+ {
+ assert(m_pData->hDC);
+
+ HBITMAP hbm = (HBITMAP)::GetCurrentObject(m_pData->hDC, OBJ_BITMAP);
+ BITMAP bm = {0};
+ ::GetObject(hbm, sizeof(bm), &bm);
+ return bm;
+ }
+
+ inline CBitmap* CDC::LoadBitmap(UINT nID)
+ // Loads a bitmap from the resource and selects it into the device context
+ {
+ return LoadBitmap(MAKEINTRESOURCE(nID));
+ }
+
+ inline CBitmap* CDC::LoadBitmap(LPCTSTR lpszName)
+ // Loads a bitmap from the resource and selects it into the device context
+ // Returns a pointer to the old bitmap selected out of the device context
+ {
+ assert(m_pData->hDC);
+
+ CBitmap* pBitmap = new CBitmap;
+ BOOL bResult = pBitmap->LoadBitmap(lpszName);
+ m_pData->m_vGDIObjects.push_back(pBitmap);
+
+ return bResult? SelectObject(pBitmap) : NULL;
+ }
+
+ inline CBitmap* CDC::LoadImage(UINT nID, int cxDesired, int cyDesired, UINT fuLoad)
+ // Loads a bitmap from the resource and selects it into the device context
+ // Returns a pointer to the old bitmap selected out of the device context
+ {
+ return LoadImage(nID, cxDesired, cyDesired, fuLoad);
+ }
+
+ inline CBitmap* CDC::LoadImage(LPCTSTR lpszName, int cxDesired, int cyDesired, UINT fuLoad)
+ // Loads a bitmap from the resource and selects it into the device context
+ // Returns a pointer to the old bitmap selected out of the device context
+ {
+ assert(m_pData->hDC);
+
+ CBitmap* pBitmap = new CBitmap;
+ BOOL bResult = pBitmap->LoadImage(lpszName, cxDesired, cyDesired, fuLoad);
+ m_pData->m_vGDIObjects.push_back(pBitmap);
+ return bResult? SelectObject(pBitmap) : NULL;
+ }
+
+ inline CBitmap* CDC::LoadOEMBitmap(UINT nIDBitmap) // for OBM_/OCR_/OIC_
+ // Loads a predefined system bitmap and selects it into the device context
+ // Returns a pointer to the old bitmap selected out of the device context
+ {
+ assert(m_pData->hDC);
+
+ CBitmap* pBitmap = new CBitmap;
+ BOOL bResult = pBitmap->LoadOEMBitmap(nIDBitmap);
+ m_pData->m_vGDIObjects.push_back(pBitmap);
+ return bResult? SelectObject(pBitmap) : NULL;
+ }
+
+#ifndef _WIN32_WCE
+ inline CBitmap* CDC::CreateMappedBitmap(UINT nIDBitmap, UINT nFlags /*= 0*/, LPCOLORMAP lpColorMap /*= NULL*/, int nMapSize /*= 0*/)
+ // creates and selects a new bitmap using the bitmap data and colors specified by the bitmap resource and the color mapping information.
+ // Returns a pointer to the old bitmap selected out of the device context
+ {
+ assert(m_pData->hDC);
+
+ CBitmap* pBitmap = new CBitmap;
+ pBitmap->CreateMappedBitmap(nIDBitmap, (WORD)nFlags, lpColorMap, nMapSize);
+ m_pData->m_vGDIObjects.push_back(pBitmap);
+ return SelectObject(pBitmap);
+ }
+#endif // !_WIN32_WCE
+
+
+ // Brush functions
+#ifndef _WIN32_WCE
+ inline CBrush* CDC::CreateBrushIndirect(LPLOGBRUSH pLogBrush)
+ // Creates the brush and selects it into the device context.
+ // Returns a pointer to the old brush selected out of the device context.
+ {
+ assert(m_pData->hDC);
+
+ CBrush* pBrush = new CBrush;
+ pBrush->CreateBrushIndirect(pLogBrush);
+ m_pData->m_vGDIObjects.push_back(pBrush);
+ return SelectObject(pBrush);
+ }
+
+ inline CBrush* CDC::CreateHatchBrush(int fnStyle, COLORREF rgb)
+ // Creates a brush with the specified hatch pattern and color, and selects it into the device context.
+ // Returns a pointer to the old brush selected out of the device context.
+ {
+ assert(m_pData->hDC);
+
+ CBrush* pBrush = new CBrush;
+ pBrush->CreateHatchBrush(fnStyle, rgb);
+ m_pData->m_vGDIObjects.push_back(pBrush);
+ return SelectObject(pBrush);
+ }
+
+ inline CBrush* CDC::CreateDIBPatternBrush(HGLOBAL hglbDIBPacked, UINT fuColorSpec)
+ // Creates a logical from the specified device-independent bitmap (DIB), and selects it into the device context.
+ // Returns a pointer to the old brush selected out of the device context.
+ {
+ assert(m_pData->hDC);
+
+ CBrush* pBrush = new CBrush;
+ pBrush->CreateDIBPatternBrush(hglbDIBPacked, fuColorSpec);
+ m_pData->m_vGDIObjects.push_back(pBrush);
+ return SelectObject(pBrush);
+ }
+
+ inline CBrush* CDC::CreateDIBPatternBrushPt(LPCVOID lpPackedDIB, UINT iUsage)
+ // Creates a logical from the specified device-independent bitmap (DIB), and selects it into the device context.
+ // Returns a pointer to the old brush selected out of the device context.
+ {
+ assert(m_pData->hDC);
+
+ CBrush* pBrush = new CBrush;
+ pBrush->CreateDIBPatternBrushPt(lpPackedDIB, iUsage);
+ m_pData->m_vGDIObjects.push_back(pBrush);
+ return SelectObject(pBrush);
+ }
+#endif
+
+ inline CBrush* CDC::CreatePatternBrush(CBitmap* pBitmap)
+ // Creates the brush with the specified pattern, and selects it into the device context.
+ // Returns a pointer to the old brush selected out of the device context.
+ {
+ assert(m_pData->hDC);
+ assert(pBitmap);
+
+ CBrush* pBrush = new CBrush;
+ pBrush->CreatePatternBrush(pBitmap);
+ m_pData->m_vGDIObjects.push_back(pBrush);
+ return SelectObject(pBrush);
+ }
+
+ inline CBrush* CDC::CreateSolidBrush(COLORREF rgb)
+ // Creates the brush with the specified color, and selects it into the device context.
+ // Returns a pointer to the old brush selected out of the device context.
+ {
+ assert(m_pData->hDC);
+
+ CBrush* pBrush = new CBrush;
+ pBrush->CreateSolidBrush(rgb);
+ m_pData->m_vGDIObjects.push_back(pBrush);
+ return SelectObject(pBrush);
+ }
+
+ inline LOGBRUSH CDC::GetLogBrush() const
+ // Retrieves the current brush information
+ {
+ assert(m_pData->hDC);
+
+ HBRUSH hBrush = (HBRUSH)::GetCurrentObject(m_pData->hDC, OBJ_BRUSH);
+ LOGBRUSH lBrush = {0};
+ ::GetObject(hBrush, sizeof(lBrush), &lBrush);
+ return lBrush;
+ }
+
+
+ // Font functions
+#ifndef _WIN32_WCE
+ inline CFont* CDC::CreateFont (
+ int nHeight, // height of font
+ int nWidth, // average character width
+ int nEscapement, // angle of escapement
+ int nOrientation, // base-line orientation angle
+ int fnWeight, // font weight
+ DWORD fdwItalic, // italic attribute option
+ DWORD fdwUnderline, // underline attribute option
+ DWORD fdwStrikeOut, // strikeout attribute option
+ DWORD fdwCharSet, // character set identifier
+ DWORD fdwOutputPrecision, // output precision
+ DWORD fdwClipPrecision, // clipping precision
+ DWORD fdwQuality, // output quality
+ DWORD fdwPitchAndFamily, // pitch and family
+ LPCTSTR lpszFace // typeface name
+ )
+
+ // Creates a logical font with the specified characteristics.
+ // Returns a pointer to the old font selected out of the device context.
+ {
+ assert(m_pData->hDC);
+
+ CFont* pFont = new CFont;
+ pFont->CreateFont (nHeight, nWidth, nEscapement, nOrientation, fnWeight,
+ fdwItalic, fdwUnderline, fdwStrikeOut, fdwCharSet,
+ fdwOutputPrecision, fdwClipPrecision, fdwQuality,
+ fdwPitchAndFamily, lpszFace);
+ m_pData->m_vGDIObjects.push_back(pFont);
+ return SelectObject(pFont);
+ }
+#endif
+
+ inline CFont* CDC::CreateFontIndirect(LPLOGFONT plf)
+ // Creates a logical font and selects it into the device context.
+ // Returns a pointer to the old font selected out of the device context.
+ {
+ assert(m_pData->hDC);
+
+ CFont* pFont = new CFont;
+ pFont->CreateFontIndirect(plf);
+ m_pData->m_vGDIObjects.push_back(pFont);
+ return SelectObject(pFont);
+ }
+
+ inline LOGFONT CDC::GetLogFont() const
+ // Retrieves the current font information.
+ {
+ assert(m_pData->hDC);
+
+ HFONT hFont = (HFONT)::GetCurrentObject(m_pData->hDC, OBJ_FONT);
+ LOGFONT lFont = {0};
+ ::GetObject(hFont, sizeof(lFont), &lFont);
+ return lFont;
+ }
+
+ // Pen functions
+ inline CPen* CDC::CreatePen (int nStyle, int nWidth, COLORREF rgb)
+ // Creates the pen and selects it into the device context.
+ // Returns a pointer to the old pen selected out of the device context.
+ {
+ assert(m_pData->hDC);
+
+ CPen* pPen = new CPen;
+ pPen->CreatePen(nStyle, nWidth, rgb);
+ m_pData->m_vGDIObjects.push_back(pPen);
+ return SelectObject(pPen);
+ }
+
+ inline CPen* CDC::CreatePenIndirect (LPLOGPEN pLogPen)
+ // Creates the pen and selects it into the device context.
+ // Returns a pointer to the old pen selected out of the device context.
+ {
+ assert(m_pData->hDC);
+
+ CPen* pPen = new CPen;
+ pPen->CreatePenIndirect(pLogPen);
+ m_pData->m_vGDIObjects.push_back(pPen);
+ return SelectObject(pPen);
+ }
+
+ inline LOGPEN CDC::GetLogPen() const
+ // Retrieves the current pen information as a LOGPEN
+ {
+ assert(m_pData->hDC);
+
+ HPEN hPen = (HPEN)::GetCurrentObject(m_pData->hDC, OBJ_PEN);
+ LOGPEN lPen = {0};
+ ::GetObject(hPen, sizeof(lPen), &lPen);
+ return lPen;
+ }
+
+ // Region functions
+ inline int CDC::CreateRectRgn(int left, int top, int right, int bottom)
+ // Creates a rectangular region from the rectangle co-ordinates.
+ // The return value specifies the region's complexity: NULLREGION;SIMPLEREGION;COMPLEXREGION;ERROR.
+ {
+ assert(m_pData->hDC);
+
+ CRgn* pRgn = new CRgn;
+ pRgn->CreateRectRgn(left, top, right, bottom);
+ m_pData->m_vGDIObjects.push_back(pRgn);
+ return SelectClipRgn(pRgn);
+ }
+
+ inline int CDC::CreateRectRgnIndirect(const RECT& rc)
+ // Creates a rectangular region from the rectangle co-ordinates.
+ // The return value specifies the region's complexity: NULLREGION;SIMPLEREGION;COMPLEXREGION;ERROR.
+ {
+ assert(m_pData->hDC);
+
+ CRgn* pRgn = new CRgn;
+ pRgn->CreateRectRgnIndirect(rc);
+ m_pData->m_vGDIObjects.push_back(pRgn);
+ return SelectClipRgn(pRgn);
+ }
+
+ inline int CDC::CreateFromData(const XFORM* Xform, DWORD nCount, const RGNDATA *pRgnData)
+ // Creates a region from the specified region data and tranformation data.
+ // The return value specifies the region's complexity: NULLREGION;SIMPLEREGION;COMPLEXREGION;ERROR.
+ // Notes: GetRegionData can be used to get a region's data
+ // If the XFROM pointer is NULL, the identity transformation is used.
+ {
+ assert(m_pData->hDC);
+
+ CRgn* pRgn = new CRgn;
+ pRgn->CreateFromData(Xform, nCount, pRgnData);
+ m_pData->m_vGDIObjects.push_back(pRgn);
+ return SelectClipRgn(pRgn);
+ }
+
+
+#ifndef _WIN32_WCE
+ inline int CDC::CreateEllipticRgn(int left, int top, int right, int bottom)
+ // Creates the ellyiptical region from the bounding rectangle co-ordinates
+ // and selects it into the device context.
+ // The return value specifies the region's complexity: NULLREGION;SIMPLEREGION;COMPLEXREGION;ERROR.
+ {
+ assert(m_pData->hDC);
+
+ CRgn* pRgn = new CRgn;
+ pRgn->CreateEllipticRgn(left, top, right, bottom);
+ m_pData->m_vGDIObjects.push_back(pRgn);
+ return SelectClipRgn(pRgn);
+ }
+
+ inline int CDC::CreateEllipticRgnIndirect(const RECT& rc)
+ // Creates the ellyiptical region from the bounding rectangle co-ordinates
+ // and selects it into the device context.
+ // The return value specifies the region's complexity: NULLREGION;SIMPLEREGION;COMPLEXREGION;ERROR.
+ {
+ assert(m_pData->hDC);
+
+ CRgn* pRgn = new CRgn;
+ pRgn->CreateEllipticRgnIndirect(rc);
+ m_pData->m_vGDIObjects.push_back(pRgn);
+ return SelectClipRgn(pRgn);
+ }
+
+ inline int CDC::CreatePolygonRgn(LPPOINT ppt, int cPoints, int fnPolyFillMode)
+ // Creates the polygon region from the array of points and selects it into
+ // the device context. The polygon is presumed closed.
+ // The return value specifies the region's complexity: NULLREGION;SIMPLEREGION;COMPLEXREGION;ERROR.
+ {
+ assert(m_pData->hDC);
+
+ CRgn* pRgn = new CRgn;
+ pRgn->CreatePolygonRgn(ppt, cPoints, fnPolyFillMode);
+ m_pData->m_vGDIObjects.push_back(pRgn);
+ return SelectClipRgn(pRgn);
+ }
+
+ inline int CDC::CreatePolyPolygonRgn(LPPOINT ppt, LPINT pPolyCounts, int nCount, int fnPolyFillMode)
+ // Creates the polygon region from a series of polygons.The polygons can overlap.
+ // The return value specifies the region's complexity: NULLREGION;SIMPLEREGION;COMPLEXREGION;ERROR.
+ {
+ assert(m_pData->hDC);
+
+ CRgn* pRgn = new CRgn;
+ pRgn->CreatePolyPolygonRgn(ppt, pPolyCounts, nCount, fnPolyFillMode);
+ m_pData->m_vGDIObjects.push_back(pRgn);
+ return SelectClipRgn(pRgn);
+ }
+#endif
+
+
+ // Wrappers for WinAPI functions
+
+ inline int CDC::GetDeviceCaps (int nIndex) const
+ // Retrieves device-specific information for the specified device.
+ {
+ assert(m_pData->hDC);
+ return ::GetDeviceCaps(m_pData->hDC, nIndex);
+ }
+
+ // Brush Functions
+#ifdef GetDCBrushColor
+ inline COLORREF CDC::GetDCBrushColor() const
+ {
+ assert(m_pData->hDC);
+ return ::GetDCBrushColor(m_pData->hDC);
+ }
+
+ inline COLORREF CDC::SetDCBrushColor(COLORREF crColor) const
+ {
+ assert(m_pData->hDC);
+ return ::SetDCBrushColor(m_pData->hDC, crColor);
+ }
+#endif
+
+ // Clipping functions
+ inline int CDC::ExcludeClipRect(int Left, int Top, int Right, int BottomRect)
+ // Creates a new clipping region that consists of the existing clipping region minus the specified rectangle.
+ {
+ assert(m_pData->hDC);
+ return ::ExcludeClipRect(m_pData->hDC, Left, Top, Right, BottomRect);
+ }
+
+ inline int CDC::ExcludeClipRect(const RECT& rc)
+ // Creates a new clipping region that consists of the existing clipping region minus the specified rectangle.
+ {
+ assert(m_pData->hDC);
+ return ::ExcludeClipRect(m_pData->hDC, rc.left, rc.top, rc.right, rc.bottom);
+ }
+
+ inline int CDC::GetClipBox (RECT& rc)
+ // Retrieves the dimensions of the tightest bounding rectangle that can be drawn around the current visible area on the device.
+ {
+ assert(m_pData->hDC);
+ return ::GetClipBox(m_pData->hDC, &rc);
+ }
+
+ inline int CDC::GetClipRgn(HRGN hrgn)
+ // Retrieves a handle identifying the current application-defined clipping region for the specified device context.
+ // hrgn: A handle to an existing region before the function is called.
+ // After the function returns, this parameter is a handle to a copy of the current clipping region.
+ {
+ assert(m_pData->hDC);
+ return ::GetClipRgn(m_pData->hDC, hrgn);
+ }
+
+ inline int CDC::IntersectClipRect(int Left, int Top, int Right, int Bottom)
+ // Creates a new clipping region from the intersection of the current clipping region and the specified rectangle.
+ {
+ assert(m_pData->hDC);
+ return ::IntersectClipRect(m_pData->hDC, Left, Top, Right, Bottom);
+ }
+
+ inline int CDC::IntersectClipRect(const RECT& rc)
+ // Creates a new clipping region from the intersection of the current clipping region and the specified rectangle.
+ {
+ assert(m_pData->hDC);
+ return ::IntersectClipRect(m_pData->hDC, rc.left, rc.top, rc.right, rc.bottom);
+ }
+
+ inline BOOL CDC::RectVisible(const RECT& rc)
+ // Determines whether any part of the specified rectangle lies within the clipping region of a device context.
+ {
+ assert(m_pData->hDC);
+ return ::RectVisible (m_pData->hDC, &rc);
+ }
+
+ inline int CDC::SelectClipRgn(CRgn* pRgn)
+ // Selects a region as the current clipping region for the specified device context.
+ // Note: Only a copy of the selected region is used.
+ // To remove a device-context's clipping region, specify a NULL region handle.
+ {
+ assert(m_pData->hDC);
+ return ::SelectClipRgn(m_pData->hDC, pRgn? (HRGN)pRgn->GetHandle() : 0);
+ }
+
+#ifndef _WIN32_WCE
+ inline int CDC::ExtSelectClipRgn(CRgn* pRgn, int fnMode)
+ // Combines the specified region with the current clipping region using the specified mode.
+ {
+ assert(m_pData->hDC);
+ assert(pRgn);
+ return ::ExtSelectClipRgn(m_pData->hDC, *pRgn, fnMode);
+ }
+#endif
+
+ inline CBitmap* CDC::SelectObject(const CBitmap* pBitmap)
+ // Use this to attach an existing bitmap.
+ {
+ assert(m_pData->hDC);
+ assert(pBitmap);
+
+ return FromHandle( (HBITMAP)::SelectObject(m_pData->hDC, *pBitmap) );
+ }
+
+ inline CBrush* CDC::SelectObject(const CBrush* pBrush)
+ // Use this to attach an existing brush.
+ {
+ assert(m_pData->hDC);
+ assert(pBrush);
+
+ return FromHandle( (HBRUSH)::SelectObject(m_pData->hDC, *pBrush) );
+ }
+
+ inline CFont* CDC::SelectObject(const CFont* pFont)
+ // Use this to attach an existing font.
+ {
+ assert(m_pData->hDC);
+ assert(pFont);
+
+ return FromHandle( (HFONT)::SelectObject(m_pData->hDC, *pFont) );
+ }
+
+ inline CPalette* CDC::SelectObject(const CPalette* pPalette)
+ // Use this to attach an existing Palette.
+ {
+ assert(m_pData->hDC);
+ assert(pPalette);
+
+ return FromHandle( (HPALETTE)::SelectObject(m_pData->hDC, *pPalette) );
+ }
+
+ inline CPen* CDC::SelectObject(const CPen* pPen)
+ // Use this to attach an existing pen.
+ {
+ assert(m_pData->hDC);
+ assert(pPen);
+
+ return FromHandle( (HPEN)::SelectObject(m_pData->hDC, *pPen) );
+ }
+
+ inline CPalette* CDC::SelectPalette(const CPalette* pPalette, BOOL bForceBkgnd)
+ // Use this to attach an existing palette.
+ {
+ assert(m_pData->hDC);
+ assert(pPalette);
+
+ return FromHandle( (HPALETTE)::SelectPalette(m_pData->hDC, *pPalette, bForceBkgnd) );
+ }
+#ifndef _WIN32_WCE
+ inline BOOL CDC::PtVisible(int X, int Y)
+ // Determines whether the specified point is within the clipping region of a device context.
+ {
+ assert(m_pData->hDC);
+ return ::PtVisible (m_pData->hDC, X, Y);
+ }
+
+ inline int CDC::OffsetClipRgn(int nXOffset, int nYOffset)
+ // Moves the clipping region of a device context by the specified offsets.
+ {
+ assert(m_pData->hDC);
+ return ::OffsetClipRgn (m_pData->hDC, nXOffset, nYOffset);
+ }
+#endif
+
+ // Point and Line Drawing Functions
+ inline CPoint CDC::GetCurrentPosition() const
+ // Returns the current "MoveToEx" position.
+ {
+ assert(m_pData->hDC);
+ CPoint pt;
+ ::MoveToEx(m_pData->hDC, 0, 0, &pt);
+ ::MoveToEx(m_pData->hDC, pt.x, pt.y, NULL);
+ return pt;
+ }
+
+ inline CPoint CDC::MoveTo(int x, int y) const
+ // Updates the current position to the specified point.
+ {
+ assert(m_pData->hDC);
+ return ::MoveToEx(m_pData->hDC, x, y, NULL);
+ }
+
+ inline CPoint CDC::MoveTo(POINT pt) const
+ // Updates the current position to the specified point
+ {
+ assert(m_pData->hDC);
+ return ::MoveToEx(m_pData->hDC, pt.x, pt.y, NULL);
+ }
+
+ inline BOOL CDC::LineTo(int x, int y) const
+ // Draws a line from the current position up to, but not including, the specified point.
+ {
+ assert(m_pData->hDC);
+ return ::LineTo(m_pData->hDC, x, y);
+ }
+
+ inline BOOL CDC::LineTo(POINT pt) const
+ // Draws a line from the current position up to, but not including, the specified point.
+ {
+ assert(m_pData->hDC);
+ return ::LineTo(m_pData->hDC, pt.x, pt.y);
+ }
+
+#ifndef _WIN32_WCE
+ inline BOOL CDC::Arc(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4) const
+ // Draws an elliptical arc.
+ {
+ assert(m_pData->hDC);
+ return ::Arc(m_pData->hDC, x1, y1, x2, y2, x3, y3, x4, y4);
+ }
+
+ inline BOOL CDC::Arc(RECT& rc, POINT ptStart, POINT ptEnd) const
+ // Draws an elliptical arc.
+ {
+ assert(m_pData->hDC);
+ return ::Arc(m_pData->hDC, rc.left, rc.top, rc.right, rc.bottom,
+ ptStart.x, ptStart.y, ptEnd.x, ptEnd.y);
+ }
+
+ inline BOOL CDC::ArcTo(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4) const
+ // Draws an elliptical arc.
+ {
+ assert(m_pData->hDC);
+ return ::ArcTo(m_pData->hDC, x1, y1, x2, y2, x3, y3, x4, y4);
+ }
+
+ inline BOOL CDC::ArcTo(RECT& rc, POINT ptStart, POINT ptEnd) const
+ // Draws an elliptical arc.
+ {
+ assert(m_pData->hDC);
+ return ::ArcTo (m_pData->hDC, rc.left, rc.top, rc.right, rc.bottom,
+ ptStart.x, ptStart.y, ptEnd.x, ptEnd.y);
+ }
+
+ inline BOOL CDC::AngleArc(int x, int y, int nRadius, float fStartAngle, float fSweepAngle) const
+ // Draws a line segment and an arc.
+ {
+ assert(m_pData->hDC);
+ return ::AngleArc(m_pData->hDC, x, y, nRadius, fStartAngle, fSweepAngle);
+ }
+
+ inline int CDC::GetArcDirection() const
+ // Retrieves the current arc direction ( AD_COUNTERCLOCKWISE or AD_CLOCKWISE ).
+ {
+ assert(m_pData->hDC);
+ return ::GetArcDirection(m_pData->hDC);
+ }
+
+ inline int CDC::SetArcDirection(int nArcDirection) const
+ // Sets the current arc direction ( AD_COUNTERCLOCKWISE or AD_CLOCKWISE ).
+ {
+ assert(m_pData->hDC);
+ return ::SetArcDirection(m_pData->hDC, nArcDirection);
+ }
+
+ inline BOOL CDC::PolyDraw(const POINT* lpPoints, const BYTE* lpTypes, int nCount) const
+ // Draws a set of line segments and Bzier curves.
+ {
+ assert(m_pData->hDC);
+ return ::PolyDraw(m_pData->hDC, lpPoints, lpTypes, nCount);
+ }
+
+ inline BOOL CDC::Polyline(LPPOINT lpPoints, int nCount) const
+ // Draws a series of line segments by connecting the points in the specified array.
+ {
+ assert(m_pData->hDC);
+ return ::Polyline(m_pData->hDC, lpPoints, nCount);
+ }
+
+ inline BOOL CDC::PolyPolyline(const POINT* lpPoints, const DWORD* lpPolyPoints, int nCount) const
+ // Draws multiple series of connected line segments.
+ {
+ assert(m_pData->hDC);
+ return ::PolyPolyline(m_pData->hDC, lpPoints, lpPolyPoints, nCount);
+ }
+
+ inline BOOL CDC::PolylineTo(const POINT* lpPoints, int nCount) const
+ // Draws one or more straight lines.
+ {
+ assert(m_pData->hDC);
+ return ::PolylineTo(m_pData->hDC, lpPoints, nCount);
+ }
+ inline BOOL CDC::PolyBezier(const POINT* lpPoints, int nCount) const
+ // Draws one or more Bzier curves.
+ {
+ assert(m_pData->hDC);
+ return ::PolyBezier(m_pData->hDC, lpPoints, nCount);
+ }
+
+ inline BOOL CDC::PolyBezierTo(const POINT* lpPoints, int nCount) const
+ // Draws one or more Bzier curves.
+ {
+ assert(m_pData->hDC);
+ return ::PolyBezierTo(m_pData->hDC, lpPoints, nCount );
+ }
+
+ inline COLORREF CDC::GetPixel(int x, int y) const
+ // Retrieves the red, green, blue (RGB) color value of the pixel at the specified coordinates.
+ {
+ assert(m_pData->hDC);
+ return ::GetPixel(m_pData->hDC, x, y);
+ }
+
+ inline COLORREF CDC::GetPixel(POINT pt) const
+ // Retrieves the red, green, blue (RGB) color value of the pixel at the specified coordinates.
+ {
+ assert(m_pData->hDC);
+ return ::GetPixel(m_pData->hDC, pt.x, pt.y);
+ }
+
+ inline COLORREF CDC::SetPixel (int x, int y, COLORREF crColor) const
+ // Sets the pixel at the specified coordinates to the specified color.
+ {
+ assert(m_pData->hDC);
+ return ::SetPixel(m_pData->hDC, x, y, crColor);
+ }
+
+ inline COLORREF CDC::SetPixel(POINT pt, COLORREF crColor) const
+ // Sets the pixel at the specified coordinates to the specified color.
+ {
+ assert(m_pData->hDC);
+ return ::SetPixel(m_pData->hDC, pt.x, pt.y, crColor);
+ }
+
+ inline BOOL CDC::SetPixelV(int x, int y, COLORREF crColor) const
+ // Sets the pixel at the specified coordinates to the closest approximation of the specified color.
+ {
+ assert(m_pData->hDC);
+ return ::SetPixelV(m_pData->hDC, x, y, crColor);
+ }
+
+ inline BOOL CDC::SetPixelV(POINT pt, COLORREF crColor) const
+ // Sets the pixel at the specified coordinates to the closest approximation of the specified color.
+ {
+ assert(m_pData->hDC);
+ return ::SetPixelV(m_pData->hDC, pt.x, pt.y, crColor);
+ }
+#endif
+
+ // Shape Drawing Functions
+ inline void CDC::DrawFocusRect(const RECT& rc) const
+ // Draws a rectangle in the style used to indicate that the rectangle has the focus.
+ {
+ assert(m_pData->hDC);
+ ::DrawFocusRect(m_pData->hDC, &rc);
+ }
+
+ inline BOOL CDC::Ellipse(int x1, int y1, int x2, int y2) const
+ // Draws an ellipse. The center of the ellipse is the center of the specified bounding rectangle.
+ {
+ assert(m_pData->hDC);
+ return ::Ellipse(m_pData->hDC, x1, y1, x2, y2);
+ }
+
+ inline BOOL CDC::Ellipse(const RECT& rc) const
+ // Draws an ellipse. The center of the ellipse is the center of the specified bounding rectangle.
+ {
+ assert(m_pData->hDC);
+ return ::Ellipse(m_pData->hDC, rc.left, rc.top, rc.right, rc.bottom);
+ }
+
+ inline BOOL CDC::Polygon(LPPOINT lpPoints, int nCount) const
+ // Draws a polygon consisting of two or more vertices connected by straight lines.
+ {
+ assert(m_pData->hDC);
+ return ::Polygon(m_pData->hDC, lpPoints, nCount);
+ }
+
+ inline BOOL CDC::Rectangle(int x1, int y1, int x2, int y2) const
+ // Draws a rectangle. The rectangle is outlined by using the current pen and filled by using the current brush.
+ {
+ assert(m_pData->hDC);
+ return ::Rectangle(m_pData->hDC, x1, y1, x2, y2);
+ }
+
+ inline BOOL CDC::Rectangle(const RECT& rc) const
+ // Draws a rectangle. The rectangle is outlined by using the current pen and filled by using the current brush.
+ {
+ assert(m_pData->hDC);
+ return ::Rectangle(m_pData->hDC, rc.left, rc.top, rc.right, rc.bottom);
+ }
+
+ inline BOOL CDC::RoundRect(int x1, int y1, int x2, int y2, int nWidth, int nHeight) const
+ // Draws a rectangle with rounded corners.
+ {
+ assert(m_pData->hDC);
+ return ::RoundRect(m_pData->hDC, x1, y1, x2, y2, nWidth, nHeight);
+ }
+ inline BOOL CDC::RoundRect(const RECT& rc, int nWidth, int nHeight) const
+ // Draws a rectangle with rounded corners.
+ {
+ assert(m_pData->hDC);
+ return ::RoundRect(m_pData->hDC, rc.left, rc.top, rc.right, rc.bottom, nWidth, nHeight );
+ }
+
+#ifndef _WIN32_WCE
+ inline BOOL CDC::Chord(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4) const
+ // Draws a chord (a region bounded by the intersection of an ellipse and a line segment, called a secant).
+ {
+ assert(m_pData->hDC);
+ return ::Chord(m_pData->hDC, x1, y1, x2, y2, x3, y3, x4, y4);
+ }
+
+ inline BOOL CDC::Chord(const RECT& rc, POINT ptStart, POINT ptEnd) const
+ // Draws a chord (a region bounded by the intersection of an ellipse and a line segment, called a secant).
+ {
+ assert(m_pData->hDC);
+ return ::Chord(m_pData->hDC, rc.left, rc.top, rc.right, rc.bottom,
+ ptStart.x, ptStart.y, ptEnd.x, ptEnd.y);
+ }
+
+ inline BOOL CDC::Pie(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4) const
+ // Draws a pie-shaped wedge bounded by the intersection of an ellipse and two radials.
+ {
+ assert(m_pData->hDC);
+ return ::Pie(m_pData->hDC, x1, y1, x2, y2, x3, y3, x4, y4);
+ }
+
+ inline BOOL CDC::Pie(const RECT& rc, POINT ptStart, POINT ptEnd) const
+ // Draws a pie-shaped wedge bounded by the intersection of an ellipse and two radials.
+ {
+ assert(m_pData->hDC);
+ return ::Pie(m_pData->hDC, rc.left, rc.top, rc.right, rc.bottom,
+ ptStart.x, ptStart.y, ptEnd.x, ptEnd.y);
+ }
+
+ inline BOOL CDC::PolyPolygon(LPPOINT lpPoints, LPINT lpPolyCounts, int nCount) const
+ // Draws a series of closed polygons.
+ {
+ assert(m_pData->hDC);
+ return ::PolyPolygon(m_pData->hDC, lpPoints, lpPolyCounts, nCount);
+ }
+#endif
+
+ // Fill and 3D Drawing functions
+ inline BOOL CDC::FillRect(const RECT& rc, CBrush* pBrush) const
+ // Fills a rectangle by using the specified brush.
+ {
+ assert(m_pData->hDC);
+ assert(pBrush);
+ return (BOOL)::FillRect(m_pData->hDC, &rc, *pBrush);
+ }
+
+ inline BOOL CDC::InvertRect(const RECT& rc) const
+ // Inverts a rectangle in a window by performing a logical NOT operation on the color values for each pixel in the rectangle's interior.
+ {
+ assert(m_pData->hDC);
+ return ::InvertRect( m_pData->hDC, &rc);
+ }
+
+ inline BOOL CDC::DrawIconEx(int xLeft, int yTop, HICON hIcon, int cxWidth, int cyWidth, UINT istepIfAniCur, CBrush* pFlickerFreeDraw, UINT diFlags) const
+ // draws an icon or cursor, performing the specified raster operations, and stretching or compressing the icon or cursor as specified.
+ {
+ assert(m_pData->hDC);
+ HBRUSH hFlickerFreeDraw = pFlickerFreeDraw? (HBRUSH)pFlickerFreeDraw->GetHandle() : NULL;
+ return ::DrawIconEx(m_pData->hDC, xLeft, yTop, hIcon, cxWidth, cyWidth, istepIfAniCur, hFlickerFreeDraw, diFlags);
+ }
+
+ inline BOOL CDC::DrawEdge(const RECT& rc, UINT nEdge, UINT nFlags) const
+ // Draws one or more edges of rectangle.
+ {
+ assert(m_pData->hDC);
+ return ::DrawEdge(m_pData->hDC, (LPRECT)&rc, nEdge, nFlags);
+ }
+
+ inline BOOL CDC::DrawFrameControl(const RECT& rc, UINT nType, UINT nState) const
+ // Draws a frame control of the specified type and style.
+ {
+ assert(m_pData->hDC);
+ return ::DrawFrameControl(m_pData->hDC, (LPRECT)&rc, nType, nState);
+ }
+
+ inline BOOL CDC::FillRgn(CRgn* pRgn, CBrush* pBrush) const
+ // Fills a region by using the specified brush.
+ {
+ assert(m_pData->hDC);
+ assert(pRgn);
+ assert(pBrush);
+ return ::FillRgn(m_pData->hDC, *pRgn, *pBrush);
+ }
+
+#ifndef _WIN32_WCE
+ inline BOOL CDC::DrawIcon(int x, int y, HICON hIcon) const
+ // Draws an icon or cursor.
+ {
+ assert(m_pData->hDC);
+ return ::DrawIcon(m_pData->hDC, x, y, hIcon);
+ }
+
+ inline BOOL CDC::DrawIcon(POINT pt, HICON hIcon) const
+ // Draws an icon or cursor.
+ {
+ assert(m_pData->hDC);
+ return ::DrawIcon(m_pData->hDC, pt.x, pt.y, hIcon);
+ }
+
+ inline BOOL CDC::FrameRect(const RECT& rc, CBrush* pBrush) const
+ // Draws a border around the specified rectangle by using the specified brush.
+ {
+ assert(m_pData->hDC);
+ assert(pBrush);
+ return (BOOL)::FrameRect(m_pData->hDC, &rc, *pBrush);
+ }
+
+ inline BOOL CDC::PaintRgn(CRgn* pRgn) const
+ // Paints the specified region by using the brush currently selected into the device context.
+ {
+ assert(m_pData->hDC);
+ assert(pRgn);
+ return ::PaintRgn(m_pData->hDC, *pRgn);
+ }
+#endif
+
+ // Bitmap Functions
+ inline int CDC::StretchDIBits(int XDest, int YDest, int nDestWidth, int nDestHeight, int XSrc, int YSrc, int nSrcWidth,
+ int nSrcHeight, CONST VOID *lpBits, BITMAPINFO& bi, UINT iUsage, DWORD dwRop) const
+ // Copies the color data for a rectangle of pixels in a DIB to the specified destination rectangle.
+ {
+ assert(m_pData->hDC);
+ return ::StretchDIBits(m_pData->hDC, XDest, YDest, nDestWidth, nDestHeight, XSrc, YSrc, nSrcWidth, nSrcHeight, lpBits, &bi, iUsage, dwRop);
+ }
+
+ inline BOOL CDC::PatBlt(int x, int y, int nWidth, int nHeight, DWORD dwRop) const
+ // Paints the specified rectangle using the brush that is currently selected into the device context.
+ {
+ assert(m_pData->hDC);
+ return ::PatBlt(m_pData->hDC, x, y, nWidth, nHeight, dwRop);
+ }
+
+ inline BOOL CDC::BitBlt(int x, int y, int nWidth, int nHeight, CDC* pSrcDC, int xSrc, int ySrc, DWORD dwRop) const
+ // Performs a bit-block transfer of the color data corresponding to a rectangle of pixels from the specified source device context into a destination device context.
+ {
+ assert(m_pData->hDC);
+ assert(pSrcDC);
+ return ::BitBlt(m_pData->hDC, x, y, nWidth, nHeight, pSrcDC->GetHDC(), xSrc, ySrc, dwRop);
+ }
+
+ inline BOOL CDC::StretchBlt(int x, int y, int nWidth, int nHeight, CDC* pSrcDC, int xSrc, int ySrc, int nSrcWidth, int nSrcHeight, DWORD dwRop) const
+ // Copies a bitmap from a source rectangle into a destination rectangle, stretching or compressing the bitmap to fit the dimensions of the destination rectangle, if necessary.
+ {
+ assert(m_pData->hDC);
+ assert(pSrcDC);
+ return ::StretchBlt(m_pData->hDC, x, y, nWidth, nHeight, pSrcDC->GetHDC(), xSrc, ySrc, nSrcWidth, nSrcHeight, dwRop);
+ }
+
+#ifndef _WIN32_WCE
+ inline int CDC::GetDIBits(CBitmap* pBitmap, UINT uStartScan, UINT cScanLines, LPVOID lpvBits, LPBITMAPINFO lpbi, UINT uUsage) const
+ // Retrieves the bits of the specified compatible bitmap and copies them into a buffer as a DIB using the specified format.
+ {
+ assert(m_pData->hDC);
+ assert(pBitmap);
+ return ::GetDIBits(m_pData->hDC, *pBitmap, uStartScan, cScanLines, lpvBits, lpbi, uUsage);
+ }
+
+ inline int CDC::SetDIBits(CBitmap* pBitmap, UINT uStartScan, UINT cScanLines, CONST VOID *lpvBits, LPBITMAPINFO lpbi, UINT fuColorUse) const
+ // Sets the pixels in a compatible bitmap (DDB) using the color data found in the specified DIB.
+ {
+ assert(m_pData->hDC);
+ return ::SetDIBits(m_pData->hDC, *pBitmap, uStartScan, cScanLines, lpvBits, lpbi, fuColorUse);
+ }
+
+ inline int CDC::GetStretchBltMode() const
+ // Retrieves the current stretching mode.
+ // Possible modes: BLACKONWHITE, COLORONCOLOR, HALFTONE, STRETCH_ANDSCANS, STRETCH_DELETESCANS, STRETCH_HALFTONE, STRETCH_ORSCANS, WHITEONBLACK
+ {
+ assert(m_pData->hDC);
+ return ::GetStretchBltMode(m_pData->hDC);
+ }
+
+ inline int CDC::SetStretchBltMode(int iStretchMode) const
+ // Sets the stretching mode.
+ // Possible modes: BLACKONWHITE, COLORONCOLOR, HALFTONE, STRETCH_ANDSCANS, STRETCH_DELETESCANS, STRETCH_HALFTONE, STRETCH_ORSCANS, WHITEONBLACK
+ {
+ assert(m_pData->hDC);
+ return ::SetStretchBltMode(m_pData->hDC, iStretchMode);
+ }
+
+ inline BOOL CDC::FloodFill(int x, int y, COLORREF crColor) const
+ // Fills an area of the display surface with the current brush.
+ {
+ assert(m_pData->hDC);
+ return ::FloodFill(m_pData->hDC, x, y, crColor);
+ }
+
+ inline BOOL CDC::ExtFloodFill(int x, int y, COLORREF crColor, UINT nFillType) const
+ // Fills an area of the display surface with the current brush.
+ // Fill type: FLOODFILLBORDER or FLOODFILLSURFACE
+ {
+ assert(m_pData->hDC);
+ return ::ExtFloodFill(m_pData->hDC, x, y, crColor, nFillType );
+ }
+
+ // co-ordinate functions
+ inline BOOL CDC::DPtoLP(LPPOINT lpPoints, int nCount) const
+ // Converts device coordinates into logical coordinates.
+ {
+ assert(m_pData->hDC);
+ return ::DPtoLP(m_pData->hDC, lpPoints, nCount);
+ }
+
+ inline BOOL CDC::DPtoLP(RECT& rc) const
+ // Converts device coordinates into logical coordinates.
+ {
+ assert(m_pData->hDC);
+ return ::DPtoLP(m_pData->hDC, (LPPOINT)&rc, 2);
+ }
+
+ inline BOOL CDC::LPtoDP(LPPOINT lpPoints, int nCount) const
+ // Converts logical coordinates into device coordinates.
+ {
+ assert(m_pData->hDC);
+ return ::LPtoDP(m_pData->hDC, lpPoints, nCount);
+ }
+
+ inline BOOL CDC::LPtoDP(RECT& rc) const
+ // Converts logical coordinates into device coordinates.
+ {
+ assert(m_pData->hDC);
+ return ::LPtoDP(m_pData->hDC, (LPPOINT)&rc, 2);
+ }
+
+#endif
+
+ // Layout Functions
+ inline DWORD CDC::GetLayout() const
+ // Returns the layout of a device context (LAYOUT_RTL and LAYOUT_BITMAPORIENTATIONPRESERVED).
+ {
+#if defined(WINVER) && defined(GetLayout) && (WINVER >= 0x0500)
+ return ::GetLayout(m_pData->hDC);
+#else
+ return 0;
+#endif
+ }
+
+ inline DWORD CDC::SetLayout(DWORD dwLayout) const
+ // changes the layout of a device context (DC).
+ // dwLayout values: LAYOUT_RTL or LAYOUT_BITMAPORIENTATIONPRESERVED
+ {
+#if defined(WINVER) && defined (SetLayout) && (WINVER >= 0x0500)
+ // Sets the layout of a device context
+ return ::SetLayout(m_pData->hDC, dwLayout);
+#else
+ UNREFERENCED_PARAMETER(dwLayout); // no-op
+ return 0;
+#endif
+ }
+
+ // Mapping Functions
+#ifndef _WIN32_WCE
+ inline int CDC::GetMapMode() const
+ // Rretrieves the current mapping mode.
+ // Possible modes: MM_ANISOTROPIC, MM_HIENGLISH, MM_HIMETRIC, MM_ISOTROPIC, MM_LOENGLISH, MM_LOMETRIC, MM_TEXT, and MM_TWIPS.
+ {
+ assert(m_pData->hDC);
+ return ::GetMapMode(m_pData->hDC);
+ }
+
+ inline BOOL CDC::GetViewportOrgEx(LPPOINT lpPoint) const
+ // Retrieves the x-coordinates and y-coordinates of the viewport origin for the device context.
+ {
+ assert(m_pData->hDC);
+ return ::GetViewportOrgEx(m_pData->hDC, lpPoint);
+ }
+
+ inline int CDC::SetMapMode(int nMapMode) const
+ // Sets the mapping mode of the specified device context.
+ {
+ assert(m_pData->hDC);
+ return ::SetMapMode(m_pData->hDC, nMapMode);
+ }
+
+ inline BOOL CDC::SetViewportOrgEx(int x, int y, LPPOINT lpPoint /* = NULL */) const
+ // Specifies which device point maps to the window origin (0,0).
+ {
+ assert(m_pData->hDC);
+ return ::SetViewportOrgEx(m_pData->hDC, x, y, lpPoint);
+ }
+
+ inline BOOL CDC::SetViewportOrgEx(POINT point, LPPOINT lpPointRet /* = NULL */) const
+ // Specifies which device point maps to the window origin (0,0).
+ {
+ assert(m_pData->hDC);
+ return SetViewportOrgEx(point.x, point.y, lpPointRet);
+ }
+
+ inline BOOL CDC::OffsetViewportOrgEx(int nWidth, int nHeight, LPPOINT lpPoint /* = NULL */) const
+ // Modifies the viewport origin for the device context using the specified horizontal and vertical offsets.
+ {
+ assert(m_pData->hDC);
+ return ::OffsetViewportOrgEx(m_pData->hDC, nWidth, nHeight, lpPoint);
+ }
+
+ inline BOOL CDC::GetViewportExtEx(LPSIZE lpSize) const
+ // Retrieves the x-extent and y-extent of the current viewport for the device context.
+ {
+ assert(m_pData->hDC);
+ return ::GetViewportExtEx(m_pData->hDC, lpSize);
+ }
+
+ inline BOOL CDC::SetViewportExtEx(int x, int y, LPSIZE lpSize ) const
+ // Sets the horizontal and vertical extents of the viewport for the device context by using the specified values.
+ {
+ assert(m_pData->hDC);
+ return ::SetViewportExtEx(m_pData->hDC, x, y, lpSize);
+ }
+
+ inline BOOL CDC::SetViewportExtEx(SIZE size, LPSIZE lpSizeRet ) const
+ // Sets the horizontal and vertical extents of the viewport for the device context by using the specified values.
+ {
+ assert(m_pData->hDC);
+ return SetViewportExtEx(size.cx, size.cy, lpSizeRet);
+ }
+
+ inline BOOL CDC::ScaleViewportExtEx(int xNum, int xDenom, int yNum, int yDenom, LPSIZE lpSize ) const
+ // Modifies the viewport for the device context using the ratios formed by the specified multiplicands and divisors.
+ {
+ assert(m_pData->hDC);
+ return ::ScaleViewportExtEx(m_pData->hDC, xNum, xDenom, yNum, yDenom, lpSize);
+ }
+
+ inline BOOL CDC::GetWindowOrgEx(LPPOINT lpPoint) const
+ // Retrieves the x-coordinates and y-coordinates of the window origin for the device context.
+ {
+ assert(m_pData->hDC);
+ return ::GetWindowOrgEx(m_pData->hDC, lpPoint);
+ }
+
+ inline BOOL CDC::SetWindowOrgEx(int x, int y, LPPOINT lpPoint ) const
+ // Specifies which window point maps to the viewport origin (0,0).
+ {
+ assert(m_pData->hDC);
+ return ::SetWindowOrgEx(m_pData->hDC, x, y, lpPoint);
+ }
+
+ inline BOOL CDC::SetWindowOrgEx(POINT point, LPPOINT lpPointRet ) const
+ // Specifies which window point maps to the viewport origin (0,0).
+ {
+ assert(m_pData->hDC);
+ return SetWindowOrgEx(point.x, point.y, lpPointRet);
+ }
+
+ inline BOOL CDC::OffsetWindowOrgEx(int nWidth, int nHeight, LPPOINT lpPoint ) const
+ // Modifies the window origin for the device context using the specified horizontal and vertical offsets.
+ {
+ assert(m_pData->hDC);
+ return ::OffsetWindowOrgEx(m_pData->hDC, nWidth, nHeight, lpPoint);
+ }
+
+ inline BOOL CDC::GetWindowExtEx(LPSIZE lpSize) const
+ // Retrieves the x-extent and y-extent of the window for the device context.
+ {
+ assert(m_pData->hDC);
+ return ::GetWindowExtEx(m_pData->hDC, lpSize);
+ }
+
+ inline BOOL CDC::SetWindowExtEx(int x, int y, LPSIZE lpSize ) const
+ // Sets the horizontal and vertical extents of the window for the device context by using the specified values.
+ {
+ assert(m_pData->hDC);
+ return ::SetWindowExtEx(m_pData->hDC, x, y, lpSize);
+ }
+
+ inline BOOL CDC::SetWindowExtEx(SIZE size, LPSIZE lpSizeRet) const
+ // Sets the horizontal and vertical extents of the window for the device context by using the specified values.
+ {
+ assert(m_pData->hDC);
+ return SetWindowExtEx(size.cx, size.cy, lpSizeRet);
+ }
+
+ inline BOOL CDC::ScaleWindowExtEx(int xNum, int xDenom, int yNum, int yDenom, LPSIZE lpSize) const
+ // Modifies the window for the device context using the ratios formed by the specified multiplicands and divisors.
+ {
+ assert(m_pData->hDC);
+ return ::ScaleWindowExtEx(m_pData->hDC, xNum, xDenom, yNum, yDenom, lpSize);
+ }
+#endif
+
+ // Printer Functions
+ inline int CDC::StartDoc(LPDOCINFO lpDocInfo) const
+ // Starts a print job.
+ {
+ assert(m_pData->hDC);
+ return ::StartDoc(m_pData->hDC, lpDocInfo);
+ }
+
+ inline int CDC::EndDoc() const
+ // Ends a print job.
+ {
+ assert(m_pData->hDC);
+ return ::EndDoc(m_pData->hDC);
+ }
+
+ inline int CDC::StartPage() const
+ // Prepares the printer driver to accept data.
+ {
+ assert(m_pData->hDC);
+ return ::StartPage(m_pData->hDC);
+ }
+
+ inline int CDC::EndPage() const
+ // Notifies the device that the application has finished writing to a page.
+ {
+ assert(m_pData->hDC);
+ return ::EndPage(m_pData->hDC);
+ }
+
+ inline int CDC::AbortDoc() const
+ // Stops the current print job and erases everything drawn since the last call to the StartDoc function.
+ {
+ assert(m_pData->hDC);
+ return ::AbortDoc(m_pData->hDC);
+ }
+
+ inline int CDC::SetAbortProc(BOOL (CALLBACK* lpfn)(HDC, int)) const
+ // Sets the application-defined abort function that allows a print job to be canceled during spooling.
+ {
+ assert(m_pData->hDC);
+ return ::SetAbortProc(m_pData->hDC, lpfn);
+ }
+
+ // Text Functions
+ inline BOOL CDC::ExtTextOut(int x, int y, UINT nOptions, LPCRECT lprc, LPCTSTR lpszString, int nCount /*= -1*/, LPINT lpDxWidths /*=NULL*/) const
+ // Draws text using the currently selected font, background color, and text color
+ {
+ assert(m_pData->hDC);
+
+ if (nCount == -1)
+ nCount = lstrlen (lpszString);
+
+ return ::ExtTextOut(m_pData->hDC, x, y, nOptions, lprc, lpszString, nCount, lpDxWidths );
+ }
+
+ inline int CDC::DrawText(LPCTSTR lpszString, int nCount, LPRECT lprc, UINT nFormat) const
+ // Draws formatted text in the specified rectangle
+ {
+ assert(m_pData->hDC);
+ return ::DrawText(m_pData->hDC, lpszString, nCount, lprc, nFormat );
+ }
+
+ inline UINT CDC::GetTextAlign() const
+ // Retrieves the text-alignment setting
+ // Values: TA_BASELINE, TA_BOTTOM, TA_TOP, TA_CENTER, TA_LEFT, TA_RIGHT, TA_RTLREADING, TA_NOUPDATECP, TA_UPDATECP
+ {
+ assert(m_pData->hDC);
+ return ::GetTextAlign(m_pData->hDC);
+ }
+
+ inline UINT CDC::SetTextAlign(UINT nFlags) const
+ // Sets the text-alignment setting
+ // Values: TA_BASELINE, TA_BOTTOM, TA_TOP, TA_CENTER, TA_LEFT, TA_RIGHT, TA_RTLREADING, TA_NOUPDATECP, TA_UPDATECP
+ {
+ assert(m_pData->hDC);
+ return ::SetTextAlign(m_pData->hDC, nFlags);
+ }
+
+ inline int CDC::GetTextFace(int nCount, LPTSTR lpszFacename) const
+ // Retrieves the typeface name of the font that is selected into the device context
+ {
+ assert(m_pData->hDC);
+ return ::GetTextFace(m_pData->hDC, nCount, lpszFacename);
+ }
+
+ inline BOOL CDC::GetTextMetrics(TEXTMETRIC& Metrics) const
+ // Fills the specified buffer with the metrics for the currently selected font
+ {
+ assert(m_pData->hDC);
+ return ::GetTextMetrics(m_pData->hDC, &Metrics);
+ }
+
+ inline COLORREF CDC::GetBkColor() const
+ // Returns the current background color
+ {
+ assert(m_pData->hDC);
+ return ::GetBkColor(m_pData->hDC);
+ }
+
+ inline COLORREF CDC::SetBkColor(COLORREF crColor) const
+ // Sets the current background color to the specified color value
+ {
+ assert(m_pData->hDC);
+ return ::SetBkColor(m_pData->hDC, crColor);
+ }
+
+ inline COLORREF CDC::GetTextColor() const
+ // Retrieves the current text color
+ {
+ assert(m_pData->hDC);
+ return ::GetTextColor(m_pData->hDC);
+ }
+
+ inline COLORREF CDC::SetTextColor(COLORREF crColor) const
+ // Sets the current text color
+ {
+ assert(m_pData->hDC);
+ return ::SetTextColor(m_pData->hDC, crColor);
+ }
+
+ inline int CDC::GetBkMode() const
+ // returns the current background mix mode (OPAQUE or TRANSPARENT)
+ {
+ assert(m_pData->hDC);
+ return ::GetBkMode(m_pData->hDC);
+ }
+
+ inline int CDC::SetBkMode(int iBkMode) const
+ // Sets the current background mix mode (OPAQUE or TRANSPARENT)
+ {
+ assert(m_pData->hDC);
+ return ::SetBkMode(m_pData->hDC, iBkMode);
+ }
+
+#ifndef _WIN32_WCE
+ inline int CDC::DrawTextEx(LPTSTR lpszString, int nCount, LPRECT lprc, UINT nFormat, LPDRAWTEXTPARAMS lpDTParams) const
+ // Draws formatted text in the specified rectangle with more formatting options
+ {
+ assert(m_pData->hDC);
+ return ::DrawTextEx(m_pData->hDC, lpszString, nCount, lprc, nFormat, lpDTParams);
+ }
+
+ inline CSize CDC::GetTextExtentPoint32(LPCTSTR lpszString, int nCount) const
+ // Computes the width and height of the specified string of text
+ {
+ assert(m_pData->hDC);
+ CSize sz;
+ ::GetTextExtentPoint32(m_pData->hDC, lpszString, nCount, &sz);
+ return sz;
+ }
+
+ inline CSize CDC::GetTabbedTextExtent(LPCTSTR lpszString, int nCount, int nTabPositions, LPINT lpnTabStopPositions) const
+ // Computes the width and height of a character string
+ {
+ assert(m_pData->hDC);
+ DWORD dwSize = ::GetTabbedTextExtent(m_pData->hDC, lpszString, nCount, nTabPositions, lpnTabStopPositions );
+ CSize sz(dwSize);
+ return sz;
+ }
+
+ inline BOOL CDC::GrayString(CBrush* pBrush, GRAYSTRINGPROC lpOutputFunc, LPARAM lpData, int nCount, int x, int y, int nWidth, int nHeight) const
+ // Draws gray text at the specified location
+ {
+ assert(m_pData->hDC);
+ assert(pBrush);
+ return ::GrayString(m_pData->hDC, *pBrush, lpOutputFunc, lpData, nCount, x, y, nWidth, nHeight);
+ }
+
+ inline int CDC::SetTextJustification(int nBreakExtra, int nBreakCount) const
+ // Specifies the amount of space the system should add to the break characters in a string of text
+ {
+ assert(m_pData->hDC);
+ return ::SetTextJustification(m_pData->hDC, nBreakExtra, nBreakCount);
+ }
+
+ inline int CDC::GetTextCharacterExtra() const
+ // Retrieves the current intercharacter spacing for the device context
+ {
+ assert(m_pData->hDC);
+ return ::GetTextCharacterExtra(m_pData->hDC);
+ }
+
+ inline int CDC::SetTextCharacterExtra(int nCharExtra) const
+ // Sets the intercharacter spacing
+ {
+ assert(m_pData->hDC);
+ return ::SetTextCharacterExtra(m_pData->hDC, nCharExtra);
+ }
+
+ inline CSize CDC::TabbedTextOut(int x, int y, LPCTSTR lpszString, int nCount, int nTabPositions, LPINT lpnTabStopPositions, int nTabOrigin) const
+ // Writes a character string at a specified location, expanding tabs to the values specified in an array of tab-stop positions
+ {
+ assert(m_pData->hDC);
+ DWORD dwSize = ::TabbedTextOut(m_pData->hDC, x, y, lpszString, nCount, nTabPositions, lpnTabStopPositions, nTabOrigin );
+ CSize sz(dwSize);
+ return sz;
+ }
+
+ inline BOOL CDC::TextOut(int x, int y, LPCTSTR lpszString, int nCount/* = -1*/) const
+ // Writes a character string at the specified location
+ {
+ assert(m_pData->hDC);
+ if (nCount == -1)
+ nCount = lstrlen (lpszString);
+
+ return ::TextOut(m_pData->hDC, x, y, lpszString, nCount);
+ }
+
+#endif
+
+
+
+ /////////////////////////////////////////////////////////////////
+ // Definitions for some global functions in the Win32xx namespace
+ //
+
+#ifndef _WIN32_WCE
+ inline void TintBitmap (CBitmap* pbmSource, int cRed, int cGreen, int cBlue)
+ // Modifies the colour of the supplied Device Dependant Bitmap, by the colour
+ // correction values specified. The correction values can range from -255 to +255.
+ // This function gains its speed by accessing the bitmap colour information
+ // directly, rather than using GetPixel/SetPixel.
+ {
+ // Create our LPBITMAPINFO object
+ CBitmapInfoPtr pbmi(pbmSource);
+ pbmi->bmiHeader.biBitCount = 24;
+
+ // Create the reference DC for GetDIBits to use
+ CMemDC MemDC(NULL);
+
+ // Use GetDIBits to create a DIB from our DDB, and extract the colour data
+ MemDC.GetDIBits(pbmSource, 0, pbmi->bmiHeader.biHeight, NULL, pbmi, DIB_RGB_COLORS);
+ std::vector<byte> vBits(pbmi->bmiHeader.biSizeImage, 0);
+ byte* pByteArray = &vBits[0];
+
+ MemDC.GetDIBits(pbmSource, 0, pbmi->bmiHeader.biHeight, pByteArray, pbmi, DIB_RGB_COLORS);
+ UINT nWidthBytes = pbmi->bmiHeader.biSizeImage/pbmi->bmiHeader.biHeight;
+
+ // Ensure sane colour correction values
+ cBlue = MIN(cBlue, 255);
+ cBlue = MAX(cBlue, -255);
+ cRed = MIN(cRed, 255);
+ cRed = MAX(cRed, -255);
+ cGreen = MIN(cGreen, 255);
+ cGreen = MAX(cGreen, -255);
+
+ // Pre-calculate the RGB modification values
+ int b1 = 256 - cBlue;
+ int g1 = 256 - cGreen;
+ int r1 = 256 - cRed;
+
+ int b2 = 256 + cBlue;
+ int g2 = 256 + cGreen;
+ int r2 = 256 + cRed;
+
+ // Modify the colour
+ int yOffset = 0;
+ int xOffset;
+ int Index;
+ for (int Row=0; Row < pbmi->bmiHeader.biHeight; Row++)
+ {
+ xOffset = 0;
+
+ for (int Column=0; Column < pbmi->bmiHeader.biWidth; Column++)
+ {
+ // Calculate Index
+ Index = yOffset + xOffset;
+
+ // Adjust the colour values
+ if (cBlue > 0)
+ pByteArray[Index] = (BYTE)(cBlue + (((pByteArray[Index] *b1)) >>8));
+ else if (cBlue < 0)
+ pByteArray[Index] = (BYTE)((pByteArray[Index] *b2) >>8);
+
+ if (cGreen > 0)
+ pByteArray[Index+1] = (BYTE)(cGreen + (((pByteArray[Index+1] *g1)) >>8));
+ else if (cGreen < 0)
+ pByteArray[Index+1] = (BYTE)((pByteArray[Index+1] *g2) >>8);
+
+ if (cRed > 0)
+ pByteArray[Index+2] = (BYTE)(cRed + (((pByteArray[Index+2] *r1)) >>8));
+ else if (cRed < 0)
+ pByteArray[Index+2] = (BYTE)((pByteArray[Index+2] *r2) >>8);
+
+ // Increment the horizontal offset
+ xOffset += pbmi->bmiHeader.biBitCount >> 3;
+ }
+
+ // Increment vertical offset
+ yOffset += nWidthBytes;
+ }
+
+ // Save the modified colour back into our source DDB
+ MemDC.SetDIBits(pbmSource, 0, pbmi->bmiHeader.biHeight, pByteArray, pbmi, DIB_RGB_COLORS);
+ }
+
+ inline void GrayScaleBitmap(CBitmap* pbmSource)
+ {
+ // Create our LPBITMAPINFO object
+ CBitmapInfoPtr pbmi(pbmSource);
+
+ // Create the reference DC for GetDIBits to use
+ CMemDC MemDC(NULL);
+
+ // Use GetDIBits to create a DIB from our DDB, and extract the colour data
+ MemDC.GetDIBits(pbmSource, 0, pbmi->bmiHeader.biHeight, NULL, pbmi, DIB_RGB_COLORS);
+ std::vector<byte> vBits(pbmi->bmiHeader.biSizeImage, 0);
+ byte* pByteArray = &vBits[0];
+
+ MemDC.GetDIBits(pbmSource, 0, pbmi->bmiHeader.biHeight, pByteArray, pbmi, DIB_RGB_COLORS);
+ UINT nWidthBytes = pbmi->bmiHeader.biSizeImage/pbmi->bmiHeader.biHeight;
+
+ int yOffset = 0;
+ int xOffset;
+ int Index;
+
+ for (int Row=0; Row < pbmi->bmiHeader.biHeight; Row++)
+ {
+ xOffset = 0;
+
+ for (int Column=0; Column < pbmi->bmiHeader.biWidth; Column++)
+ {
+ // Calculate Index
+ Index = yOffset + xOffset;
+
+ BYTE byGray = (BYTE) ((pByteArray[Index] + pByteArray[Index+1]*6 + pByteArray[Index+2] *3)/10);
+ pByteArray[Index] = byGray;
+ pByteArray[Index+1] = byGray;
+ pByteArray[Index+2] = byGray;
+
+ // Increment the horizontal offset
+ xOffset += pbmi->bmiHeader.biBitCount >> 3;
+ }
+
+ // Increment vertical offset
+ yOffset += nWidthBytes;
+ }
+
+ // Save the modified colour back into our source DDB
+ MemDC.SetDIBits(pbmSource, 0, pbmi->bmiHeader.biHeight, pByteArray, pbmi, DIB_RGB_COLORS);
+ }
+
+ inline HIMAGELIST CreateDisabledImageList(HIMAGELIST himlNormal)
+ // Returns a greyed image list, created from hImageList
+ {
+ int cx, cy;
+ int nCount = ImageList_GetImageCount(himlNormal);
+ if (0 == nCount)
+ return NULL;
+
+ ImageList_GetIconSize(himlNormal, &cx, &cy);
+
+ // Create the disabled ImageList
+ HIMAGELIST himlDisabled = ImageList_Create(cx, cy, ILC_COLOR24 | ILC_MASK, nCount, 0);
+
+ // Process each image in the ImageList
+ for (int i = 0 ; i < nCount; ++i)
+ {
+ CClientDC DesktopDC(NULL);
+ CMemDC MemDC(NULL);
+ CBitmap* pOldBitmap = MemDC.CreateCompatibleBitmap(&DesktopDC, cx, cx);
+ CRect rc;
+ rc.SetRect(0, 0, cx, cx);
+
+ // Set the mask color to grey for the new ImageList
+ COLORREF crMask = RGB(200, 199, 200);
+ if ( GetDeviceCaps(DesktopDC, BITSPIXEL) < 24)
+ {
+ HPALETTE hPal = (HPALETTE)GetCurrentObject(DesktopDC, OBJ_PAL);
+ UINT Index = GetNearestPaletteIndex(hPal, crMask);
+ if (Index != CLR_INVALID) crMask = PALETTEINDEX(Index);
+ }
+
+ MemDC.SolidFill(crMask, rc);
+
+ // Draw the image on the memory DC
+ ImageList_SetBkColor(himlNormal, crMask);
+ ImageList_Draw(himlNormal, i, MemDC, 0, 0, ILD_NORMAL);
+
+ // Convert colored pixels to gray
+ for (int x = 0 ; x < cx; ++x)
+ {
+ for (int y = 0; y < cy; ++y)
+ {
+ COLORREF clr = ::GetPixel(MemDC, x, y);
+
+ if (clr != crMask)
+ {
+ BYTE byGray = (BYTE) (95 + (GetRValue(clr) *3 + GetGValue(clr)*6 + GetBValue(clr))/20);
+ MemDC.SetPixel(x, y, RGB(byGray, byGray, byGray));
+ }
+
+ }
+ }
+
+ // Detach the bitmap so we can use it.
+ CBitmap* pBitmap = MemDC.SelectObject(pOldBitmap);
+ ImageList_AddMasked(himlDisabled, *pBitmap, crMask);
+ }
+
+ return himlDisabled;
+ }
+#endif
+
+ ////////////////////////////////////////////
+ // Global Function Definitions
+ //
+
+ inline CDC* FromHandle(HDC hDC)
+ // Returns the CDC object associated with the device context handle
+ // If a CDC object doesn't already exist, a temporary CDC object is created.
+ // The HDC belonging to a temporary CDC is not released or destroyed when the
+ // temporary CDC is deconstructed.
+ {
+ assert( GetApp() );
+ CDC* pDC = GetApp()->GetCDCFromMap(hDC);
+ if (hDC != 0 && pDC == 0)
+ {
+ pDC = new CDC;
+ GetApp()->AddTmpDC(pDC);
+ pDC->m_pData->hDC = hDC;
+ pDC->m_pData->bRemoveHDC = FALSE;
+ }
+ return pDC;
+ }
+
+ inline CBitmap* FromHandle(HBITMAP hBitmap)
+ // Returns the CBitmap associated with the Bitmap handle
+ // If a CBitmap object doesn't already exist, a temporary CBitmap object is created.
+ // The HBITMAP belonging to a temporary CBitmap is not released or destroyed
+ // when the temporary CBitmap is deconstructed.
+ {
+ assert( GetApp() );
+ CBitmap* pBitmap = (CBitmap*)GetApp()->GetCGDIObjectFromMap(hBitmap);
+ if (hBitmap != 0 && pBitmap == 0)
+ {
+ pBitmap = new CBitmap;
+ GetApp()->AddTmpGDI(pBitmap);
+ pBitmap->m_pData->hGDIObject = hBitmap;
+ pBitmap->m_pData->bRemoveObject = FALSE;
+ }
+ return pBitmap;
+ }
+
+ inline CBrush* FromHandle(HBRUSH hBrush)
+ // Returns the CBrush associated with the Brush handle
+ // If a CBrush object doesn't already exist, a temporary CBrush object is created.
+ // The HBRUSH belonging to a temporary CBrush is not released or destroyed
+ // when the temporary CBrush is deconstructed.
+ {
+ assert( GetApp() );
+ CBrush* pBrush = (CBrush*)GetApp()->GetCGDIObjectFromMap(hBrush);
+ if (hBrush != 0 && pBrush == 0)
+ {
+ pBrush = new CBrush;
+ GetApp()->AddTmpGDI(pBrush);
+ pBrush->m_pData->hGDIObject = hBrush;
+ pBrush->m_pData->bRemoveObject = FALSE;
+ }
+ return pBrush;
+ }
+
+ inline CFont* FromHandle(HFONT hFont)
+ // Returns the CFont associated with the Font handle
+ // If a CFont object doesn't already exist, a temporary CFont object is created.
+ // The HFONT belonging to a temporary CFont is not released or destroyed
+ // when the temporary CFont is deconstructed.
+ {
+ assert( GetApp() );
+ CFont* pFont = (CFont*)GetApp()->GetCGDIObjectFromMap(hFont);
+ if (hFont != 0 && pFont == 0)
+ {
+ pFont = new CFont;
+ GetApp()->AddTmpGDI(pFont);
+ pFont->m_pData->hGDIObject = hFont;
+ pFont->m_pData->bRemoveObject = FALSE;
+ }
+ return pFont;
+ }
+
+ inline CPalette* FromHandle(HPALETTE hPalette)
+ // Returns the CPalette associated with the palette handle
+ // If a CPalette object doesn't already exist, a temporary CPalette object is created.
+ // The HPALETTE belonging to a temporary CPalette is not released or destroyed
+ // when the temporary CPalette is deconstructed.
+ {
+ assert( GetApp() );
+ CPalette* pPalette = (CPalette*)GetApp()->GetCGDIObjectFromMap(hPalette);
+ if (hPalette != 0 && pPalette == 0)
+ {
+ pPalette = new CPalette;
+ GetApp()->AddTmpGDI(pPalette);
+ pPalette->m_pData->hGDIObject = hPalette;
+ pPalette->m_pData->bRemoveObject = FALSE;
+ }
+ return pPalette;
+ }
+
+ inline CPen* FromHandle(HPEN hPen)
+ // Returns the CPen associated with the HPEN.
+ // If a CPen object doesn't already exist, a temporary CPen object is created.
+ // The HPEN belonging to a temporary CPen is not released or destroyed
+ // when the temporary CPen is deconstructed.
+ {
+ assert( GetApp() );
+ CPen* pPen = (CPen*)GetApp()->GetCGDIObjectFromMap(hPen);
+ if (hPen != 0 && pPen == 0)
+ {
+ pPen = new CPen;
+ GetApp()->AddTmpGDI(pPen);
+ pPen->m_pData->hGDIObject = hPen;
+ pPen->m_pData->bRemoveObject = FALSE;
+ }
+ return pPen;
+ }
+
+ inline CRgn* FromHandle(HRGN hRgn)
+ // Returns the CRgn associated with the HRGN.
+ // If a CRgn object doesn't already exist, a temporary CRgn object is created.
+ // The HRGN belonging to a temporary CRgn is not released or destroyed
+ // when the temporary CRgn is deconstructed.
+ {
+ assert( GetApp() );
+ CRgn* pRgn = (CRgn*)GetApp()->GetCGDIObjectFromMap(hRgn);
+ if (hRgn != 0 && pRgn == 0)
+ {
+ pRgn = new CRgn;
+ GetApp()->AddTmpGDI(pRgn);
+ pRgn->m_pData->hGDIObject = hRgn;
+ pRgn->m_pData->bRemoveObject = FALSE;
+ }
+ return pRgn;
+ }
+
+
+
+} // namespace Win32xx
+
+#endif // _WIN32XX_GDI_H_
+
diff --git a/mmc_updater/depends/win32cpp/info.txt b/mmc_updater/depends/win32cpp/info.txt
new file mode 100644
index 00000000..a4dbda8e
--- /dev/null
+++ b/mmc_updater/depends/win32cpp/info.txt
@@ -0,0 +1,205 @@
+Generic Information about Win32++ Projects
+==========================================
+The various directories may contain the following types of files:
+
+Extension | Description
+----------+------------
+cbp | A project file used by CodeBlocks
+dsp | A project file used by Visual Studio 6
+dsw | A project file used by Visual Studio 6
+sln | A project file used by Visual Studio 2003, VS2005 or VS2008
+vcproj | A project file used by Visual Studio 2003, VS2005 or VS2008
+vcxproj | A project file used by Visual Studio 2010
+filters | A supplementary project file used by Visual Studio 2010
+bdsproj | A project file used by Borland Developer Studio 2006
+bpf | A project file used by Borland Developer Studio 2006
+vcp | A project file used by eMbedded Visual C++
+vcw | A project file used by eMbedded Visual C++
+dev | A project file used by Dev-C++
+cpp | A C++ source file
+h | A C++ header file
+rc | A C++ resouce script file
+jpg | A jpeg resource file
+ico | An icon resource file
+bmp | A bitmap resource file
+cur | A cursor resource file
+manifest | A manifest resource file
+txt | A text file
+xml | An Extensible Markup Language file (defines the ribbon UI)
+
+Supported Compilers and Integrated Development Environments (IDEs)
+==================================================================
+Win32++ supports the following:
+* Borland Compiler Version 5.5
+* Borland Developer Studio 2006
+* Borland Turbo C++ 2006
+* CodeBlocks
+* Dev-C++
+* MinGW GCC Compiler
+* Visual Studio 6
+* Visual Studio.net 2003
+* Visual C++ Toolkit 2003
+* Visual Studio.net 2005
+* Visual Studio.net 2005 Express
+* Visual Studio.net 2008
+* Visual Studio.net 2008 Express
+* Visual Studio.net 2010
+
+CodeBlocks is an IDE. The project files are configured for the following
+compilers:
+* Borland Compiler Version 5.5
+* MinGW GNU compiler
+* Visual C++ Toolkit 2003
+
+Dev-C++ is an IDE which supports the MinGW GNU compiler
+
+Supported Operating Systems
+===========================
+The programs compiled with Win32++ can run on the following operating systems:
+* Win95 (all versions, with or without Internet Explorer 4 installed)
+* Win98 (both versions)
+* WinME
+* Windows NT 4
+* Windows 2000
+* Windows XP
+* Windows XP x64
+* Windows Vista
+* Windows Vista x64
+* Windows 7
+* Windows 7 x64
+* Windows Server 2003
+* Windows Server 2003 x64
+* Windows Server 2008
+* Windows Server 2008 x64
+* Windows CE
+
+Note: Programs compiled with Visual Studio.net 2008 and Visual Studio.net 2008
+Express will not run on Win32 operating systems earlier than Windows 2000.
+
+Win32++ automatically detects if the operating system is capable of using
+rebars. If rebars are not supported by the OS, Win32++ produces a frame without
+rebars.
+
+Win32++ is Unicode compliant and can therefore be used to develop Unicode
+applications. Users are advised that older operating systems (namely Win95,
+Win98 and WinME) don't support Unicode applications.
+
+Win32++ supports 64bit compilers, and can be used to develop 64bit code.
+
+Directory Structure
+===================
+When extracting the files from the zip archive, be sure to preserve the
+directory structure. The directory structure will typically look like this:
+
+.\include
+.\new projects
+.\output
+.\samples
+.\tools
+.\tutorials
+.\WCE samples
+
+The files which form the Win32++ library are contained in the include
+subdirectory.
+
+Components of Win32++
+=====================
+
+ Files | Classes | Operating Systems | Description
+==================+==================+===================+=====================
+controls.h | CAnimation | Win32, Win64 | Adds support for the
+ | CComboBox | and WinCE | following controls:
+ | CComboBoxEx | | Animation, ComboBox,
+ | CProgressBar | | ComboBoxEx, Progress
+ | CScrollBar | | bar, Scroll bar,
+ | CSlider | | Slider, Spin button.
+ | CSpinButton | |
+------------------+------------------+-------------------+---------------------
+dialog.h | CDialog | Win32, Win64 | Adds dialog support.
+ | CResizer | WinCE for CDialog |
+------------------+------------------+-------------------+---------------------
+docking.h | CDocker | Win32, Win64 | Adds support for
+ | CDockContainer | | docking windows and
+ | | | splitter windows.
+------------------+------------------+-------------------+---------------------
+frame.h | CMenubar | Win32, Win64 | Adds support for
+ | CFrame | | frames. Frames use a
+ | | | toolbar and menubar
+ | | | inside a rebar, and
+ | | | a statusbar.
+------------------+------------------+-------------------+---------------------
+gdi.h | CDC | Win32, Win64 | A helper class for
+ | CBitmap | and WinCE | GDI graphics.
+ | CBrush | |
+ | CFont | |
+ | CPalette | |
+ | CPen | |
+ | CRgn | |
+------------------+------------------+-------------------+---------------------
+listView.h | CListView | Win32, Win64 | Adds support for a
+ | | and WinCE | ListView control.
+------------------+------------------+-------------------+---------------------
+mdi.h | CMDIFrame | Win32, Win64 | Adds support for MDI
+ | CMDIChild | | frames.
+------------------+------------------+-------------------+---------------------
+propertysheet.h | CPropertySheet | Win32, Win64 | Adds property sheet
+ | CPropertyPage | and WinCE | support.
+------------------+------------------+-------------------+---------------------
+rebar.h | CRebar | Win32, Win64 | Adds support for a
+ | | and WinCE | Rebar control.
+------------------+------------------+-------------------+---------------------
+ribbon.h | CRibbon | Win32, Win64 | Adds support for the
+ | CRibbonFrame | | Windows 7 ribbon.
+------------------+------------------+-------------------+---------------------
+shared_ptr.h | Shared_Ptr | Win32, Win64, | Add a smart pointer
+ | | and WinCE | for use in vectors.
+------------------+------------------+-------------------+---------------------
+socket.h | CSocket | Win32, Win64 | Adds network
+ | | and WinCE | support.
+------------------+------------------+-------------------+---------------------
+splitter.h | CSplitter | Win32, Win64 | Adds splitter support
+ | | | (depreciated)
+------------------+------------------+-------------------+----------------------
+statusbar.h | CStatusbar | Win32, Win64 | Adds support for a
+ | | and WinCE | Status bar control.
+------------------+------------------+-------------------+---------------------
+stdcontrols.h | CButton | Win32, Win64 | Adds support for
+ | CEdit | and WinCE | Button, Edit,
+ | CListBox | | ListBox and Static
+ | CStatic | | controls.
+------------------+------------------+-------------------+---------------------
+tab.h | CTab | Win32, Win64 | Adds support for tab
+ | CMDITab | | controls, and MDI
+ | | | tab windows.
+------------------+------------------+-------------------+---------------------
+taskdialog.h | CTaskDialog | Win32, Win64 | Adds support for tab
+ | | | task dialogs.
+------------------+------------------+-------------------+---------------------
+thread.h | CThread | Win32, Win64 | Adds support for
+ | | and WinCE | threads.
+------------------+------------------+-------------------+---------------------
+toolbar.h | CToolbar | Win32, Win64 | Adds support for a
+ | | and WinCE | Toolbar control.
+------------------+------------------+-------------------+---------------------
+treeview.h | CTreeView | Win32, Win64 | Adds support for a
+ | | and WinCE | TreeView control.
+------------------+------------------+-------------------+---------------------
+wceframe.h | CWceFrame | WinCE only | Adds support for
+ | CCmdbar | | frames in WinCE.
+------------------+------------------+-------------------+---------------------
+webbrowser.h | CAXWindow | Win32, Win64 | Adds support for a
+ | CWebBrowser | and WinCE | ActiveX container and
+ | | | a WebBrowser window.
+------------------+------------------+-------------------+---------------------
+wincore.h | CCriticalSection | Win32, Win64, | The core set of
+ | CWinApp | and WinCE | classes required for
+ | CWinException | | all Win32++
+ | CWnd | | applications.
+------------------+------------------+-------------------+---------------------
+winutils.h | CPoint | Win32, Win64, | Additional utility
+ | CRect | and WinCE | classes.
+ | CSize | |
+------------------+------------------+-------------------+---------------------
+
+Refer to the help documentation that ships with Win32++ for more information on
+using Win32++. \ No newline at end of file
diff --git a/mmc_updater/depends/win32cpp/listview.h b/mmc_updater/depends/win32cpp/listview.h
new file mode 100644
index 00000000..810e7627
--- /dev/null
+++ b/mmc_updater/depends/win32cpp/listview.h
@@ -0,0 +1,867 @@
+// Win32++ Version 7.2
+// Released: 5th AUgust 2011
+//
+// David Nash
+// email: dnash@bigpond.net.au
+// url: https://sourceforge.net/projects/win32-framework
+//
+//
+// Copyright (c) 2005-2011 David Nash
+//
+// Permission is hereby granted, free of charge, to
+// any person obtaining a copy of this software and
+// associated documentation files (the "Software"),
+// to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify,
+// merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom
+// the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice
+// shall be included in all copies or substantial portions
+// of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
+// OR OTHER DEALINGS IN THE SOFTWARE.
+//
+////////////////////////////////////////////////////////
+
+
+
+#ifndef _WIN32XX_LISTVIEW_H_
+#define _WIN32XX_LISTVIEW_H_
+
+#include "wincore.h"
+#include "commctrl.h"
+
+namespace Win32xx
+{
+
+ class CListView : public CWnd
+ {
+ public:
+ CListView() {}
+ virtual ~CListView() {}
+ virtual void PreRegisterClass(WNDCLASS &wc);
+
+ // Attributes
+ CSize ApproximateViewRect(CSize sz = CSize(-1, -1), int iCount = -1) const;
+ COLORREF GetBkColor( ) const;
+ BOOL GetBkImage( LVBKIMAGE& lvbkImage ) const;
+ UINT GetCallbackMask( ) const;
+ BOOL GetCheckState( UINT nItem ) const;
+ BOOL GetColumn( int iCol, LVCOLUMN& Column ) const;
+ BOOL GetColumnOrderArray( LPINT piArray, int iCount = -1 );
+ int GetColumnWidth( int iCol ) const;
+ int GetCountPerPage( ) const;
+ HWND GetEditControl( ) const;
+ DWORD GetExtendedStyle( ) const;
+ HWND GetHeader( ) const;
+ HCURSOR GetHotCursor( );
+ int GetHotItem( ) const;
+ DWORD GetHoverTime( ) const;
+ HIMAGELIST GetImageList( int nImageType ) const;
+ BOOL GetItem( LVITEM& lvItem ) const;
+ int GetItemCount( ) const;
+ DWORD_PTR GetItemData( int iItem ) const;
+ BOOL GetItemPosition( int iItem, CPoint& pt ) const;
+ BOOL GetItemRect( int iItem, CRect& rc, UINT nCode ) const;
+ UINT GetItemState( int iItem, UINT nMask ) const;
+ tString GetItemText( int iItem, int iSubItem, UINT nTextMax = 260 ) const;
+ int GetNextItem( int iItem, int iFlags ) const;
+ UINT GetNumberOfWorkAreas( ) const;
+ BOOL GetOrigin( CPoint& pt ) const;
+ UINT GetSelectedCount( ) const;
+ int GetSelectionMark( ) const;
+ int GetStringWidth( LPCTSTR pszString ) const;
+ BOOL GetSubItemRect( int iItem, int iSubItem, int iCode, CRect& rc ) const;
+ COLORREF GetTextBkColor( ) const;
+ COLORREF GetTextColor( ) const;
+ HWND GetToolTips( ) const;
+ int GetTopIndex( ) const;
+ BOOL GetViewRect( CRect& rc ) const;
+ void GetWorkAreas( int iWorkAreas, LPRECT pRectArray ) const;
+ BOOL SetBkColor( COLORREF clrBk ) const;
+ BOOL SetBkImage( LVBKIMAGE& plvbkImage ) const;
+ BOOL SetCallbackMask( UINT nMask ) const;
+ void SetCheckState( int iItem, BOOL fCheck = TRUE ) const;
+ BOOL SetColumn( int iCol, const LVCOLUMN& pColumn ) const;
+ BOOL SetColumnOrderArray( int iCount, LPINT piArray ) const;
+ BOOL SetColumnWidth( int iCol, int cx ) const;
+ DWORD SetExtendedStyle( DWORD dwNewStyle ) const;
+ HCURSOR SetHotCursor( HCURSOR hCursor ) const;
+ int SetHotItem( int nIndex ) const;
+ DWORD SetHoverTime( DWORD dwHoverTime = (DWORD)-1 ) const;
+ CSize SetIconSpacing( int cx, int cy ) const;
+ CSize SetIconSpacing( CSize sz ) const;
+ HIMAGELIST SetImageList( HIMAGELIST himl, int iImageListType ) const;
+ BOOL SetItem( LVITEM& pItem ) const;
+ BOOL SetItem( int iItem, int iSubItem, UINT nMask, LPCTSTR pszText, int iImage,
+ UINT nState, UINT nStateMask, LPARAM lParam, int iIndent ) const;
+ void SetItemCount( int iCount ) const;
+ void SetItemCountEx( int iCount, DWORD dwFlags = LVSICF_NOINVALIDATEALL ) const;
+ BOOL SetItemData( int iItem, DWORD_PTR dwData ) const;
+ BOOL SetItemPosition( int iItem, CPoint& pt ) const;
+ BOOL SetItemState( int iItem, LVITEM& Item ) const;
+ void SetItemState( int iItem, UINT nState, UINT nMask ) const;
+ void SetItemText( int iItem, int iSubItem, LPCTSTR pszText ) const;
+ int SetSelectionMark( int iIndex ) const;
+ BOOL SetTextBkColor( COLORREF clrBkText ) const;
+ BOOL SetTextColor( COLORREF clrText ) const;
+ HWND SetToolTips( HWND hWndToolTip ) const;
+ void SetWorkAreas( int nWorkAreas, CRect& pRectArray ) const;
+ int SubItemHitTest( LVHITTESTINFO& htInfo ) const;
+
+ // Operations
+ BOOL Arrange( UINT nCode ) const;
+ HIMAGELIST CreateDragImage( int iItem, CPoint& pt ) const;
+ BOOL DeleteAllItems( ) const;
+ BOOL DeleteColumn( int iCol ) const;
+ BOOL DeleteItem( int iItem ) const;
+ HWND EditLabel( int iItem ) const;
+ BOOL EnsureVisible( int iItem, BOOL fPartialOK ) const;
+ int FindItem( LVFINDINFO& FindInfo, int iStart = -1 ) const;
+ int HitTest( LVHITTESTINFO& HitTestInfo ) const;
+ int HitTest( CPoint pt, UINT* pFlags = NULL ) const;
+ int InsertColumn( int iCol, const LVCOLUMN& pColumn ) const;
+ int InsertColumn( int iCol, LPCTSTR pszColumnHeading, int iFormat = LVCFMT_LEFT,
+ int iWidth = -1, int iSubItem = -1 ) const;
+ int InsertItem( const LVITEM& pItem ) const;
+ int InsertItem( int iItem, LPCTSTR pszText ) const;
+ int InsertItem( int iItem, LPCTSTR pszText, int iImage ) const;
+ BOOL RedrawItems( int iFirst, int iLast ) const;
+ BOOL Scroll( CSize sz ) const;
+ BOOL SortItems( PFNLVCOMPARE pfnCompare, DWORD_PTR dwData ) const;
+ BOOL Update( int iItem ) const;
+
+ private:
+ CListView(const CListView&); // Disable copy construction
+ CListView& operator = (const CListView&); // Disable assignment operator
+ };
+
+}
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+namespace Win32xx
+{
+
+ inline void CListView::PreRegisterClass(WNDCLASS &wc)
+ {
+ // Set the Window Class
+ wc.lpszClassName = WC_LISTVIEW;
+ }
+
+ inline CSize CListView::ApproximateViewRect(CSize sz /*= CSize(-1, -1)*/, int iCount /* = -1*/) const
+ // Calculates the approximate width and height required to display a given number of items.
+ {
+ assert(::IsWindow(m_hWnd));
+ return CSize( ListView_ApproximateViewRect( m_hWnd, sz.cx, sz.cy, iCount ) );
+ }
+
+ inline COLORREF CListView::GetBkColor( ) const
+ // Retrieves the background color of a list-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_GetBkColor( m_hWnd );
+ }
+
+ inline BOOL CListView::GetBkImage( LVBKIMAGE& lvbkImage ) const
+ // Retrieves the background image in a list-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_GetBkImage( m_hWnd, &lvbkImage );
+ }
+
+ inline UINT CListView::GetCallbackMask( ) const
+ // Retrieves the callback mask for a list-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_GetCallbackMask( m_hWnd );
+ }
+
+ inline BOOL CListView::GetCheckState( UINT nItem ) const
+ // Determines if an item in a list-view control is selected.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_GetCheckState( m_hWnd, nItem );
+ }
+
+ inline BOOL CListView::GetColumn( int iCol, LVCOLUMN& Column ) const
+ // Retrieves the attributes of a list-view control's column.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_GetColumn( m_hWnd, iCol, &Column );
+ }
+
+ inline BOOL CListView::GetColumnOrderArray( LPINT piArray, int iCount /*= -1*/ )
+ // Retrieves the current left-to-right order of columns in a list-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_GetColumnOrderArray( m_hWnd, iCount, piArray );
+ }
+
+ inline int CListView::GetColumnWidth( int iCol ) const
+ // Retrieves the width of a column in report or list view.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_GetColumnWidth( m_hWnd, iCol );
+ }
+
+ inline int CListView::GetCountPerPage( ) const
+ // Calculates the number of items that can fit vertically in the visible area of a
+ // list-view control when in list or report view. Only fully visible items are counted.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_GetCountPerPage( m_hWnd );
+ }
+
+ inline HWND CListView::GetEditControl( ) const
+ // Retrieves the handle to the edit control being used to edit a list-view item's text.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_GetEditControl( m_hWnd );
+ }
+
+ inline DWORD CListView::GetExtendedStyle( ) const
+ // Retrieves the extended styles that are currently in use for a given list-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_GetExtendedListViewStyle( m_hWnd );
+ }
+
+ inline HWND CListView::GetHeader( ) const
+ // Retrieves the handle to the header control used by a list-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_GetHeader( m_hWnd );
+ }
+
+ inline HCURSOR CListView::GetHotCursor( )
+ // Retrieves the HCURSOR used when the pointer is over an item while hot tracking is enabled.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_GetHotCursor( m_hWnd );
+ }
+
+ inline int CListView::GetHotItem( ) const
+ // Retrieves the index of the hot item.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_GetHotItem( m_hWnd );
+ }
+
+ inline DWORD CListView::GetHoverTime( ) const
+ // Retrieves the amount of time that the mouse cursor must hover over an item before it is selected.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_GetHoverTime( m_hWnd );
+ }
+
+ inline HIMAGELIST CListView::GetImageList( int nImageType ) const
+ // Retrieves the handle to an image list used for drawing list-view items.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_GetImageList( m_hWnd, nImageType );
+ }
+
+ inline BOOL CListView::GetItem( LVITEM& Item ) const
+ // Retrieves some or all of a list-view item's attributes.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_GetItem( m_hWnd, &Item );
+ }
+
+ inline int CListView::GetItemCount( ) const
+ // Retrieves the number of items in a list-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_GetItemCount( m_hWnd );
+ }
+
+ inline DWORD_PTR CListView::GetItemData( int iItem ) const
+ // Retrieves the value(lParam) specific to the item.
+ {
+ assert(::IsWindow(m_hWnd));
+
+ LVITEM lvi = {0};
+ lvi.iItem = iItem;
+ lvi.mask = LVIF_PARAM;
+ ListView_GetItem(m_hWnd, &lvi);
+ return lvi.lParam;
+ }
+
+ inline BOOL CListView::GetItemPosition( int iItem, CPoint& pt ) const
+ // Retrieves the position of a list-view item.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_GetItemPosition( m_hWnd, iItem, &pt );
+ }
+
+ inline BOOL CListView::GetItemRect( int iItem, CRect& rc, UINT nCode ) const
+ // Retrieves the bounding rectangle for all or part of an item in the current view.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_GetItemRect( m_hWnd, iItem, &rc, nCode );
+ }
+
+ inline UINT CListView::GetItemState( int iItem, UINT nMask ) const
+ // Retrieves the state of a list-view item.
+
+ // Possible values of nMask:
+ // LVIS_CUT The item is marked for a cut-and-paste operation.
+ // LVIS_DROPHILITED The item is highlighted as a drag-and-drop target.
+ // LVIS_FOCUSED The item has the focus, so it is surrounded by a standard focus rectangle.
+ // LVIS_SELECTED The item is selected.
+ // LVIS_OVERLAYMASK Use this mask to retrieve the item's overlay image index.
+ // LVIS_STATEIMAGEMASK Use this mask to retrieve the item's state image index.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_GetItemState( m_hWnd, iItem, nMask );
+ }
+
+ inline tString CListView::GetItemText( int iItem, int iSubItem, UINT nTextMax /* = 260 */ ) const
+ // Retrieves the text of a list-view item.
+ // Note: Although the list-view control allows any length string to be stored
+ // as item text, only the first 260 characters are displayed.
+ {
+ assert(::IsWindow(m_hWnd));
+
+ tString t;
+ if (nTextMax > 0)
+ {
+ std::vector<TCHAR> vTChar(nTextMax +1, _T('\0'));
+ TCHAR* pszText = &vTChar.front();
+ LVITEM lvi = {0};
+ lvi.iItem = iItem;
+ lvi.iSubItem = iSubItem;
+ lvi.mask = LVIF_TEXT;
+ lvi.cchTextMax = nTextMax;
+ lvi.pszText = pszText;
+ ListView_GetItem( m_hWnd, &lvi );
+ t = lvi.pszText;
+ }
+ return t;
+ }
+
+ inline int CListView::GetNextItem( int iItem, int iFlags ) const
+ // Searches for a list-view item that has the specified properties and
+ // bears the specified relationship to a specified item.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_GetNextItem( m_hWnd, iItem, iFlags );
+ }
+
+ inline UINT CListView::GetNumberOfWorkAreas( ) const
+ // Retrieves the working areas from a list-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+ UINT nWorkAreas = 0;
+ ListView_GetWorkAreas( m_hWnd, nWorkAreas, NULL );
+ return nWorkAreas;
+ }
+
+ inline BOOL CListView::GetOrigin( CPoint& pt ) const
+ // Retrieves the current view origin for a list-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_GetOrigin( m_hWnd, &pt );
+ }
+
+ inline UINT CListView::GetSelectedCount( ) const
+ // Determines the number of selected items in a list-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (UINT)::SendMessage( m_hWnd, LVM_GETSELECTEDCOUNT, 0L, 0L );
+ }
+
+ inline int CListView::GetSelectionMark( ) const
+ // Retrieves the selection mark from a list-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (int)::SendMessage( m_hWnd, LVM_GETSELECTIONMARK, 0L, 0L );
+ }
+
+ inline int CListView::GetStringWidth( LPCTSTR pszString ) const
+ // Determines the width of a specified string using the specified list-view control's current font.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (int)::SendMessage( m_hWnd, LVM_GETSTRINGWIDTH, 0L, (LPARAM)pszString );
+ }
+
+ inline BOOL CListView::GetSubItemRect( int iItem, int iSubItem, int iCode, CRect& rc ) const
+ // Retrieves information about the rectangle that surrounds a subitem in a list-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_GetSubItemRect( m_hWnd, iItem, iSubItem, iCode, &rc );
+ }
+
+ inline COLORREF CListView::GetTextBkColor( ) const
+ // Retrieves the text background color of a list-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_GetTextBkColor( m_hWnd );
+ }
+
+ inline COLORREF CListView::GetTextColor( ) const
+ // Retrieves the text color of a list-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_GetTextColor( m_hWnd );
+ }
+
+ inline HWND CListView::GetToolTips( ) const
+ // Retrieves the ToolTip control that the list-view control uses to display ToolTips.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_GetToolTips( m_hWnd );
+ }
+
+ inline int CListView::GetTopIndex( ) const
+ // Retrieves the index of the topmost visible item when in list or report view.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_GetTopIndex( m_hWnd );
+ }
+
+ inline BOOL CListView::GetViewRect( CRect& rc ) const
+ // Retrieves the bounding rectangle of all items in the list-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_GetViewRect( m_hWnd, &rc );
+ }
+
+ inline void CListView::GetWorkAreas( int iWorkAreas, LPRECT pRectArray ) const
+ // Retrieves the working areas from a list-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+ ListView_GetWorkAreas( m_hWnd, iWorkAreas, pRectArray );
+ }
+
+ inline BOOL CListView::SetBkColor( COLORREF clrBk ) const
+ // Sets the background color of a list-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_SetBkColor( m_hWnd, clrBk );
+ }
+
+ inline BOOL CListView::SetBkImage( LVBKIMAGE& lvbkImage ) const
+ // Sets the background image in a list-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_SetBkImage( m_hWnd, &lvbkImage );
+ }
+
+ inline BOOL CListView::SetCallbackMask( UINT nMask ) const
+ // Changes the callback mask for a list-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_SetCallbackMask( m_hWnd, nMask );
+ }
+
+ inline void CListView::SetCheckState( int iItem, BOOL fCheck /*= TRUE*/ ) const
+ // Used to select or deselect an item in a list-view control.
+ // This macro should only be used for list-view controls with the LVS_EX_CHECKBOXES style.
+ {
+ assert(::IsWindow(m_hWnd));
+ ListView_SetItemState(m_hWnd, iItem, INDEXTOSTATEIMAGEMASK((fCheck==TRUE)?2:1),LVIS_STATEIMAGEMASK);
+ }
+
+ inline BOOL CListView::SetColumn( int iCol, const LVCOLUMN& Column ) const
+ // Sets the attributes of a list-view column.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_SetColumn( m_hWnd, iCol, &Column );
+ }
+
+ inline BOOL CListView::SetColumnOrderArray( int iCount, LPINT piArray ) const
+ // Sets the left-to-right order of columns in a list-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_SetColumnOrderArray( m_hWnd, iCount, piArray );
+ }
+
+ inline BOOL CListView::SetColumnWidth( int iCol, int cx ) const
+ // Used to change the width of a column in report view or the width of all columns in list-view mode.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_SetColumnWidth( m_hWnd, iCol, cx );
+ }
+
+ inline DWORD CListView::SetExtendedStyle( DWORD dwNewStyle ) const
+ // Sets extended styles for list-view controls.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_SetExtendedListViewStyle( m_hWnd, dwNewStyle );
+ }
+
+ inline HCURSOR CListView::SetHotCursor( HCURSOR hCursor ) const
+ // Sets the HCURSOR that the list-view control uses when the pointer is
+ // over an item while hot tracking is enabled.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_SetHotCursor( m_hWnd, hCursor );
+ }
+
+ inline int CListView::SetHotItem( int nIndex ) const
+ // Sets the hot item in a list-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_SetHotItem( m_hWnd, nIndex );
+ }
+
+ inline DWORD CListView::SetHoverTime( DWORD dwHoverTime /*= (DWORD)-1*/ ) const
+ // Sets the amount of time that the mouse cursor must hover over an item before it is selected.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_SetHoverTime( m_hWnd, dwHoverTime );
+ }
+
+ inline CSize CListView::SetIconSpacing( int cx, int cy ) const
+ // Sets the spacing between icons in list-view controls set to the LVS_ICON style.
+ {
+ assert(::IsWindow(m_hWnd));
+ return CSize( ListView_SetIconSpacing( m_hWnd, cx, cy ) );
+ }
+
+ inline CSize CListView::SetIconSpacing( CSize sz ) const
+ // Sets the spacing between icons in list-view controls set to the LVS_ICON style.
+ {
+ assert(::IsWindow(m_hWnd));
+ return CSize( ListView_SetIconSpacing( m_hWnd, sz.cx, sz.cy ) );
+ }
+
+ inline HIMAGELIST CListView::SetImageList( HIMAGELIST himl, int iImageListType ) const
+ // Assigns an image list to a list-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_SetImageList( m_hWnd, himl, iImageListType );
+ }
+
+ inline BOOL CListView::SetItem( LVITEM& Item ) const
+ // Sets some or all of a list-view item's attributes.
+
+ // The declaration for TVITEM:
+ // typedef struct _LVITEM {
+ // UINT mask;
+ // int iItem;
+ // int iSubItem;
+ // UINT state;
+ // UINT stateMask;
+ // LPTSTR pszText;
+ // int cchTextMax;
+ // int iImage;
+ // LPARAM lParam;
+ // } LVITEM, *LVITEM&;
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_SetItem( m_hWnd, &Item );
+ }
+
+ inline BOOL CListView::SetItem( int iItem, int iSubItem, UINT nMask, LPCTSTR pszText, int iImage,
+ UINT nState, UINT nStateMask, LPARAM lParam, int iIndent ) const
+ // Sets some or all of a list-view item's attributes.
+ {
+ assert(::IsWindow(m_hWnd));
+
+ LVITEM lvi = {0};
+ lvi.iItem = iItem;
+ lvi.iSubItem = iSubItem;
+ lvi.mask = nMask;
+ lvi.pszText = (LPTSTR)pszText;
+ lvi.iImage = iImage;
+ lvi.state = nState;
+ lvi.stateMask = nStateMask;
+ lvi.lParam = lParam;
+ lvi.iIndent = iIndent;
+
+ return ListView_SetItem( m_hWnd, &lvi);
+ }
+
+ inline void CListView::SetItemCount( int iCount ) const
+ // Causes the list-view control to allocate memory for the specified number of items.
+ {
+ assert(::IsWindow(m_hWnd));
+ ListView_SetItemCount( m_hWnd, iCount );
+ }
+
+ inline void CListView::SetItemCountEx( int iCount, DWORD dwFlags /*= LVSICF_NOINVALIDATEALL*/ ) const
+ // Sets the virtual number of items in a virtual list view.
+ {
+ assert(::IsWindow(m_hWnd));
+ ListView_SetItemCountEx( m_hWnd, iCount, dwFlags );
+ }
+
+ inline BOOL CListView::SetItemData( int iItem, DWORD_PTR dwData ) const
+ // Sets the value(lParam) specific to the item.
+ {
+ assert(::IsWindow(m_hWnd));
+
+ LVITEM lvi = {0};
+ lvi.iItem = iItem;
+ lvi.lParam = dwData;
+ lvi.mask = LVIF_PARAM;
+ return ListView_SetItem(m_hWnd, &lvi);
+ }
+
+ inline BOOL CListView::SetItemPosition( int iItem, CPoint& pt ) const
+ // Moves an item to a specified position in a list-view control (in icon or small icon view).
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_SetItemPosition( m_hWnd, iItem, pt.x, pt.y );
+ }
+
+ inline BOOL CListView::SetItemState( int iItem, LVITEM& Item ) const
+ // Changes the state of an item in a list-view control.
+
+ // Possible values of nMask:
+ // LVIS_CUT The item is marked for a cut-and-paste operation.
+ // LVIS_DROPHILITED The item is highlighted as a drag-and-drop target.
+ // LVIS_FOCUSED The item has the focus, so it is surrounded by a standard focus rectangle.
+ // LVIS_SELECTED The item is selected.
+ // LVIS_OVERLAYMASK Use this mask to retrieve the item's overlay image index.
+ // LVIS_STATEIMAGEMASK Use this mask to retrieve the item's state image index.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (BOOL)::SendMessage(m_hWnd, LVM_SETITEMSTATE, (WPARAM)iItem, (LPARAM)&Item);
+ }
+
+ inline void CListView::SetItemState( int iItem, UINT nState, UINT nMask ) const
+ // Changes the state of an item in a list-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+ ListView_SetItemState(m_hWnd, iItem, nState, nMask);
+ }
+
+ inline void CListView::SetItemText( int iItem, int iSubItem, LPCTSTR pszText ) const
+ // Sets the text color of a list-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+ ListView_SetItemText(m_hWnd, iItem, iSubItem, (LPTSTR)pszText );
+ }
+
+ inline int CListView::SetSelectionMark( int iIndex ) const
+ // Sets the selection mark in a list-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_SetSelectionMark( m_hWnd, iIndex );
+ }
+
+ inline BOOL CListView::SetTextBkColor( COLORREF clrBkText ) const
+ // Sets the background color of text in a list-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_SetTextBkColor( m_hWnd, clrBkText );
+ }
+
+ inline BOOL CListView::SetTextColor( COLORREF clrText ) const
+ // Sets the text color of a list-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_SetTextColor( m_hWnd, clrText );
+ }
+
+ inline HWND CListView::SetToolTips( HWND hWndToolTip ) const
+ // Sets the ToolTip control that the list-view control will use to display ToolTips.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (HWND)::SendMessage(m_hWnd, LVM_SETTOOLTIPS, (WPARAM)hWndToolTip, 0L);
+ }
+
+ inline void CListView::SetWorkAreas( int nWorkAreas, CRect& pRectArray ) const
+ // Sets the working area within a list-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+ ListView_SetWorkAreas( m_hWnd, nWorkAreas, pRectArray );
+ }
+
+ inline int CListView::SubItemHitTest( LVHITTESTINFO& htInfo ) const
+ // Determines which list-view item or subitem is located at a given position.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_SubItemHitTest( m_hWnd, &htInfo );
+ }
+
+ // Operations
+
+ inline BOOL CListView::Arrange( UINT nCode ) const
+ // Arranges items in icon view.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_Arrange( m_hWnd, nCode );
+ }
+
+ inline HIMAGELIST CListView::CreateDragImage( int iItem, CPoint& pt ) const
+ // Creates a drag image list for the specified item.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_CreateDragImage( m_hWnd, iItem, &pt );
+ }
+
+ inline BOOL CListView::DeleteAllItems( ) const
+ // ListView_DeleteAllItems
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_DeleteAllItems( m_hWnd );
+ }
+
+ inline BOOL CListView::DeleteColumn( int iCol ) const
+ // Removes a column from a list-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_DeleteColumn( m_hWnd, iCol );
+ }
+
+ inline BOOL CListView::DeleteItem( int iItem ) const
+ // Removes an item from a list-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_DeleteItem( m_hWnd, iItem );
+ }
+
+ inline HWND CListView::EditLabel( int iItem ) const
+ // Begins in-place editing of the specified list-view item's text.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_EditLabel( m_hWnd, iItem );
+ }
+
+ inline BOOL CListView::EnsureVisible( int iItem, BOOL fPartialOK ) const
+ // Ensures that a list-view item is either entirely or partially visible,
+ // scrolling the list-view control if necessary.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (BOOL)SendMessage(LVM_ENSUREVISIBLE, (WPARAM)iItem, (LPARAM)fPartialOK );
+ }
+
+ inline int CListView::FindItem( LVFINDINFO& FindInfo, int iStart /*= -1*/ ) const
+ // Searches for a list-view item with the specified characteristics.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_FindItem( m_hWnd, iStart, &FindInfo );
+ }
+
+ inline int CListView::HitTest( LVHITTESTINFO& HitTestInfo ) const
+ // Determines which list-view item, if any, is at a specified position.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_HitTest( m_hWnd, &HitTestInfo );
+ }
+
+ inline int CListView::HitTest( CPoint pt, UINT* pFlags /*= NULL*/ ) const
+ // Determines which list-view item, if any, is at a specified position.
+ {
+ assert(::IsWindow(m_hWnd));
+
+ LVHITTESTINFO hti = {0};
+ hti.flags = *pFlags;
+ hti.pt = pt;
+ return ListView_HitTest( m_hWnd, &hti );
+ }
+
+ inline int CListView::InsertColumn( int iCol, const LVCOLUMN& Column ) const
+ // Inserts a new column in a list-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_InsertColumn( m_hWnd, iCol, &Column );
+ }
+
+ inline int CListView::InsertColumn( int iCol, LPCTSTR pszColumnHeading, int iFormat /*= LVCFMT_LEFT*/,
+ int iWidth /*= -1*/, int iSubItem /*= -1*/ ) const
+ // Inserts a new column in a list-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+
+ LVCOLUMN lvc = {0};
+ lvc.mask = LVCF_TEXT|LVCF_ORDER|LVCF_FMT;
+ if (-1 != iWidth)
+ {
+ lvc.mask |= LVCF_WIDTH;
+ lvc.cx = iWidth;
+ }
+ if (-1 != iSubItem)
+ {
+ lvc.mask |= LVCF_SUBITEM;
+ lvc.iSubItem = iSubItem;
+ }
+
+ lvc.iOrder = iCol;
+ lvc.pszText = (LPTSTR)pszColumnHeading;
+ lvc.fmt = iFormat;
+ lvc.iSubItem = iSubItem;
+ return ListView_InsertColumn( m_hWnd, iCol, &lvc );
+ }
+
+ inline int CListView::InsertItem( const LVITEM& Item ) const
+ // Inserts a new item in a list-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_InsertItem( m_hWnd, &Item );
+ }
+
+ inline int CListView::InsertItem( int iItem, LPCTSTR pszText ) const
+ // Inserts a new item in a list-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+
+ LVITEM lvi = {0};
+ lvi.iItem = iItem;
+ lvi.pszText = (LPTSTR)pszText;
+ lvi.mask = LVIF_TEXT;
+ return ListView_InsertItem( m_hWnd, &lvi );
+ }
+
+ inline int CListView::InsertItem( int iItem, LPCTSTR pszText, int iImage ) const
+ // Inserts a new item in a list-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+
+ LVITEM lvi = {0};
+ lvi.iItem = iItem;
+ lvi.pszText = (LPTSTR)pszText;
+ lvi.iImage = iImage;
+ lvi.mask = LVIF_TEXT | LVIF_IMAGE;
+ return ListView_InsertItem( m_hWnd, &lvi );
+ }
+
+ inline BOOL CListView::RedrawItems( int iFirst, int iLast ) const
+ // Forces a list-view control to redraw a range of items.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_RedrawItems( m_hWnd, iFirst, iLast );
+ }
+
+ inline BOOL CListView::Scroll( CSize sz ) const
+ // Scrolls the content of a list-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_Scroll( m_hWnd, sz.cx, sz.cy );
+ }
+
+ inline BOOL CListView::SortItems( PFNLVCOMPARE pfnCompare, DWORD_PTR dwData ) const
+ // Uses an application-defined comparison function to sort the items of a list-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_SortItems( m_hWnd, pfnCompare, dwData );
+ }
+
+ inline BOOL CListView::Update( int iItem ) const
+ // Updates a list-view item. If the list-view control has the LVS_AUTOARRANGE style,
+ // the list-view control is rearranged.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_Update( m_hWnd, iItem );
+ }
+
+} // namespace Win32xx
+
+#endif // #ifndef _WIN32XX_LISTVIEW_H_
+
diff --git a/mmc_updater/depends/win32cpp/mdi.h b/mmc_updater/depends/win32cpp/mdi.h
new file mode 100644
index 00000000..0aa35ffc
--- /dev/null
+++ b/mmc_updater/depends/win32cpp/mdi.h
@@ -0,0 +1,783 @@
+// Released: 5th AUgust 2011
+//
+// David Nash
+// email: dnash@bigpond.net.au
+// url: https://sourceforge.net/projects/win32-framework
+//
+//
+// Copyright (c) 2005-2011 David Nash
+//
+// Permission is hereby granted, free of charge, to
+// any person obtaining a copy of this software and
+// associated documentation files (the "Software"),
+// to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify,
+// merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom
+// the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice
+// shall be included in all copies or substantial portions
+// of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
+// OR OTHER DEALINGS IN THE SOFTWARE.
+//
+////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////
+// mdi.h
+// Declaration of the CMDIChild and CMDIFrame classes
+
+// The classes defined here add MDI frames support to Win32++. MDI
+// (Multiple Document Interface) frames host one or more child windows. The
+// child windows hosted by a MDI frame can be different types. For example,
+// some MDI child windows could be used to edit text, while others could be
+// used to display a bitmap. Four classes are defined here to support MDI
+// frames:
+
+
+// 1) CMDIFrame. This class inherits from CFrame, and adds the functionality
+// required by MDI frames. It keeps track of the MDI children created and
+// destroyed, and adjusts the menu when a MDI child is activated. Use the
+// AddMDIChild function to add MDI child windows to the MDI frame. Inherit
+// from CMDIFrame to create your own MDI frame.
+//
+// 2) CMDIChild: All MDI child windows (ie. CWnd classes) should inherit from
+// this class. Each MDI child type can have a different frame menu.
+
+// Use the MDIFrame generic application as the starting point for your own MDI
+// frame applications.
+// Refer to the MDIDemo sample for an example on how to use these classes to
+// create a MDI frame application with different types of MDI child windows.
+
+
+#ifndef _WIN32XX_MDI_H_
+#define _WIN32XX_MDI_H_
+
+#include "frame.h"
+#include <vector>
+
+
+
+namespace Win32xx
+{
+ class CMDIChild;
+ class CMDIFrame;
+ typedef Shared_Ptr<CMDIChild> MDIChildPtr;
+
+ /////////////////////////////////////
+ // Declaration of the CMDIChild class
+ //
+ class CMDIChild : public CWnd
+ {
+ friend class CMDIFrame;
+ public:
+ CMDIChild();
+ virtual ~CMDIChild();
+
+ // These are the functions you might wish to override
+ virtual HWND Create(CWnd* pParent = NULL);
+ virtual void RecalcLayout();
+
+ // These functions aren't virtual, and shouldn't be overridden
+ void SetHandles(HMENU MenuName, HACCEL AccelName);
+ CMDIFrame* GetMDIFrame() const;
+ CWnd* GetView() const {return m_pView;}
+ void SetView(CWnd& pwndView);
+ void MDIActivate() const;
+ void MDIDestroy() const;
+ void MDIMaximize() const;
+ void MDIRestore() const;
+
+ protected:
+ // Its unlikely you would need to override these functions
+ virtual LRESULT FinalWindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam);
+ virtual void OnCreate();
+ virtual LRESULT WndProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam);
+
+ private:
+ CMDIChild(const CMDIChild&); // Disable copy construction
+ CMDIChild& operator = (const CMDIChild&); // Disable assignment operator
+
+ CWnd* m_pView; // pointer to the View CWnd object
+ HMENU m_hChildMenu;
+ HACCEL m_hChildAccel;
+ };
+
+
+ /////////////////////////////////////
+ // Declaration of the CMDIFrame class
+ //
+ class CMDIFrame : public CFrame
+ {
+ friend class CMDIChild; // CMDIChild uses m_hOrigMenu
+ typedef Shared_Ptr<CMDIChild> MDIChildPtr;
+
+ public:
+ class CMDIClient : public CWnd // a nested class within CMDIFrame
+ {
+ public:
+ CMDIClient() {}
+ virtual ~CMDIClient() {}
+ virtual HWND Create(CWnd* pParent = NULL);
+ virtual LRESULT WndProc(UINT uMsg, WPARAM wParam, LPARAM lParam);
+ CMDIFrame* GetMDIFrame() const { return (CMDIFrame*)GetParent(); }
+
+ private:
+ CMDIClient(const CMDIClient&); // Disable copy construction
+ CMDIClient& operator = (const CMDIClient&); // Disable assignment operator
+ };
+
+
+ CMDIFrame();
+ virtual ~CMDIFrame() {}
+
+ virtual CMDIChild* AddMDIChild(MDIChildPtr pMDIChild);
+ virtual CMDIClient& GetMDIClient() const { return (CMDIClient&)m_MDIClient; }
+ virtual BOOL IsMDIFrame() const { return TRUE; }
+ virtual void RemoveMDIChild(HWND hWnd);
+ virtual BOOL RemoveAllMDIChildren();
+ virtual void UpdateCheckMarks();
+
+ // These functions aren't virtual, so don't override them
+ std::vector <MDIChildPtr>& GetAllMDIChildren() {return m_vMDIChild;}
+ CMDIChild* GetActiveMDIChild() const;
+ BOOL IsMDIChildMaxed() const;
+ void MDICascade(int nType = 0) const;
+ void MDIIconArrange() const;
+ void MDIMaximize() const;
+ void MDINext() const;
+ void MDIPrev() const;
+ void MDIRestore() const;
+ void MDITile(int nType = 0) const;
+ void SetActiveMDIChild(CMDIChild* pChild);
+
+ protected:
+ // These are the functions you might wish to override
+ virtual void OnClose();
+ virtual void OnViewStatusBar();
+ virtual void OnViewToolBar();
+ virtual void OnWindowPosChanged();
+ virtual void RecalcLayout();
+ virtual BOOL PreTranslateMessage(MSG* pMsg);
+ virtual LRESULT WndProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam);
+
+ private:
+ CMDIFrame(const CMDIFrame&); // Disable copy construction
+ CMDIFrame& operator = (const CMDIFrame&); // Disable assignment operator
+ void AppendMDIMenu(HMENU hMenuWindow);
+ LRESULT FinalWindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam);
+ void UpdateFrameMenu(HMENU hMenu);
+
+ CMDIClient m_MDIClient;
+ std::vector <MDIChildPtr> m_vMDIChild;
+ HWND m_hActiveMDIChild;
+ };
+
+}
+
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+namespace Win32xx
+{
+
+ /////////////////////////////////////
+ // Definitions for the CMDIFrame class
+ //
+ inline CMDIFrame::CMDIFrame() : m_hActiveMDIChild(NULL)
+ {
+ SetView(GetMDIClient());
+ }
+
+ inline CMDIChild* CMDIFrame::AddMDIChild(MDIChildPtr pMDIChild)
+ {
+ assert(NULL != pMDIChild.get()); // Cannot add Null MDI Child
+
+ m_vMDIChild.push_back(pMDIChild);
+ pMDIChild->Create(GetView());
+
+ return pMDIChild.get();
+ }
+
+ inline void CMDIFrame::AppendMDIMenu(HMENU hMenuWindow)
+ {
+ // Adds the additional menu items the the "Window" submenu when
+ // MDI child windows are created
+
+ if (!IsMenu(hMenuWindow))
+ return;
+
+ // Delete previously appended items
+ int nItems = ::GetMenuItemCount(hMenuWindow);
+ UINT uLastID = ::GetMenuItemID(hMenuWindow, --nItems);
+ if ((uLastID >= IDW_FIRSTCHILD) && (uLastID < IDW_FIRSTCHILD + 10))
+ {
+ while ((uLastID >= IDW_FIRSTCHILD) && (uLastID < IDW_FIRSTCHILD + 10))
+ {
+ ::DeleteMenu(hMenuWindow, nItems, MF_BYPOSITION);
+ uLastID = ::GetMenuItemID(hMenuWindow, --nItems);
+ }
+ //delete the separator too
+ ::DeleteMenu(hMenuWindow, nItems, MF_BYPOSITION);
+ }
+
+ int nWindow = 0;
+
+ // Allocate an iterator for our MDIChild vector
+ std::vector <MDIChildPtr>::iterator v;
+
+ for (v = GetAllMDIChildren().begin(); v < GetAllMDIChildren().end(); ++v)
+ {
+ if ((*v)->GetWindowLongPtr(GWL_STYLE) & WS_VISIBLE) // IsWindowVisible is unreliable here
+ {
+ // Add Separator
+ if (0 == nWindow)
+ ::AppendMenu(hMenuWindow, MF_SEPARATOR, 0, NULL);
+
+ // Add a menu entry for each MDI child (up to 9)
+ if (nWindow < 9)
+ {
+ tString tsMenuItem ( (*v)->GetWindowText() );
+
+ if (tsMenuItem.length() > MAX_MENU_STRING -10)
+ {
+ // Truncate the string if its too long
+ tsMenuItem.erase(tsMenuItem.length() - MAX_MENU_STRING +10);
+ tsMenuItem += _T(" ...");
+ }
+
+ TCHAR szMenuString[MAX_MENU_STRING+1];
+ wsprintf(szMenuString, _T("&%d %s"), nWindow+1, tsMenuItem.c_str());
+
+ ::AppendMenu(hMenuWindow, MF_STRING, IDW_FIRSTCHILD + nWindow, szMenuString);
+
+ if (GetActiveMDIChild() == (*v).get())
+ ::CheckMenuItem(hMenuWindow, IDW_FIRSTCHILD+nWindow, MF_CHECKED);
+
+ ++nWindow;
+ }
+ else if (9 == nWindow)
+ // For the 10th MDI child, add this menu item and return
+ {
+ ::AppendMenu(hMenuWindow, MF_STRING, IDW_FIRSTCHILD + nWindow, _T("&Windows..."));
+ return;
+ }
+ }
+ }
+ }
+
+ inline LRESULT CMDIFrame::FinalWindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
+ {
+ return ::DefFrameProc(m_hWnd, GetMDIClient(), uMsg, wParam, lParam);
+ }
+
+ inline CMDIChild* CMDIFrame::GetActiveMDIChild() const
+ {
+ return (CMDIChild*)FromHandle(m_hActiveMDIChild);
+ }
+
+ inline BOOL CMDIFrame::IsMDIChildMaxed() const
+ {
+ BOOL bMaxed = FALSE;
+ GetMDIClient().SendMessage(WM_MDIGETACTIVE, 0L, (LPARAM)&bMaxed);
+ return bMaxed;
+ }
+
+ inline void CMDIFrame::MDICascade(int nType /* = 0*/) const
+ {
+ // Possible values for nType are:
+ // MDITILE_SKIPDISABLED Prevents disabled MDI child windows from being cascaded.
+
+ assert(::IsWindow(m_hWnd));
+ GetView()->SendMessage(WM_MDICASCADE, (WPARAM)nType, 0L);
+ }
+
+ inline void CMDIFrame::MDIIconArrange() const
+ {
+ assert(::IsWindow(m_hWnd));
+ GetView()->SendMessage(WM_MDIICONARRANGE, 0L, 0L);
+ }
+
+ inline void CMDIFrame::MDIMaximize() const
+ {
+ assert(::IsWindow(m_hWnd));
+ GetView()->SendMessage(WM_MDIMAXIMIZE, 0L, 0L);
+ }
+
+ inline void CMDIFrame::MDINext() const
+ {
+ assert(::IsWindow(m_hWnd));
+ HWND hMDIChild = GetActiveMDIChild()->GetHwnd();
+ GetView()->SendMessage(WM_MDINEXT, (WPARAM)hMDIChild, FALSE);
+ }
+
+ inline void CMDIFrame::MDIPrev() const
+ {
+ assert(::IsWindow(m_hWnd));
+ HWND hMDIChild = GetActiveMDIChild()->GetHwnd();
+ GetView()->SendMessage(WM_MDINEXT, (WPARAM)hMDIChild, TRUE);
+ }
+
+ inline void CMDIFrame::MDIRestore() const
+ {
+ assert(::IsWindow(m_hWnd));
+ GetView()->SendMessage(WM_MDIRESTORE, 0L, 0L);
+ }
+
+ inline void CMDIFrame::MDITile(int nType /* = 0*/) const
+ {
+ // Possible values for nType are:
+ // MDITILE_HORIZONTAL Tiles MDI child windows so that one window appears above another.
+ // MDITILE_SKIPDISABLED Prevents disabled MDI child windows from being tiled.
+ // MDITILE_VERTICAL Tiles MDI child windows so that one window appears beside another.
+
+ assert(::IsWindow(m_hWnd));
+ GetView()->SendMessage(WM_MDITILE, (WPARAM)nType, 0L);
+ }
+
+ inline void CMDIFrame::OnClose()
+ {
+ if (RemoveAllMDIChildren())
+ {
+ CFrame::OnClose();
+ Destroy();
+ }
+ }
+
+ inline void CMDIFrame::OnViewStatusBar()
+ {
+ CFrame::OnViewStatusBar();
+ UpdateCheckMarks();
+ GetView()->RedrawWindow(NULL, NULL, RDW_FRAME | RDW_INVALIDATE | RDW_ERASE | RDW_ALLCHILDREN);
+ }
+
+ inline void CMDIFrame::OnViewToolBar()
+ {
+ CFrame::OnViewToolBar();
+ UpdateCheckMarks();
+ GetView()->RedrawWindow(NULL, NULL, RDW_FRAME | RDW_INVALIDATE | RDW_ERASE | RDW_ALLCHILDREN);
+ }
+
+ inline void CMDIFrame::OnWindowPosChanged()
+ {
+ if (IsMenuBarUsed())
+ {
+ // Refresh MenuBar Window
+ HMENU hMenu= GetMenuBar().GetMenu();
+ GetMenuBar().SetMenu(hMenu);
+ UpdateCheckMarks();
+ }
+ }
+
+ inline BOOL CMDIFrame::PreTranslateMessage(MSG* pMsg)
+ {
+ if (WM_KEYFIRST <= pMsg->message && pMsg->message <= WM_KEYLAST)
+ {
+ if (TranslateMDISysAccel(GetView()->GetHwnd(), pMsg))
+ return TRUE;
+ }
+
+ return CFrame::PreTranslateMessage(pMsg);
+ }
+
+ inline void CMDIFrame::RecalcLayout()
+ {
+ CFrame::RecalcLayout();
+
+ if (GetView()->IsWindow())
+ MDIIconArrange();
+ }
+
+ inline BOOL CMDIFrame::RemoveAllMDIChildren()
+ {
+ BOOL bResult = TRUE;
+ int Children = (int)m_vMDIChild.size();
+
+ // Remove the children in reverse order
+ for (int i = Children-1; i >= 0; --i)
+ {
+ if (IDNO == m_vMDIChild[i]->SendMessage(WM_CLOSE, 0L, 0L)) // Also removes the MDI child
+ bResult = FALSE;
+ }
+
+ return bResult;
+ }
+
+ inline void CMDIFrame::RemoveMDIChild(HWND hWnd)
+ {
+ // Allocate an iterator for our HWND map
+ std::vector <MDIChildPtr>::iterator v;
+
+ for (v = m_vMDIChild.begin(); v!= m_vMDIChild.end(); ++v)
+ {
+ if ((*v)->GetHwnd() == hWnd)
+ {
+ m_vMDIChild.erase(v);
+ break;
+ }
+ }
+
+ if (GetActiveMDIChild())
+ {
+ if (GetActiveMDIChild()->m_hChildMenu)
+ UpdateFrameMenu(GetActiveMDIChild()->m_hChildMenu);
+ if (GetActiveMDIChild()->m_hChildAccel)
+ GetApp()->SetAccelerators(GetActiveMDIChild()->m_hChildAccel, this);
+ }
+ else
+ {
+ if (IsMenuBarUsed())
+ GetMenuBar().SetMenu(GetFrameMenu());
+ else
+ SetMenu(FromHandle(GetFrameMenu()));
+
+ GetApp()->SetAccelerators(GetFrameAccel(), this);
+ }
+ }
+
+ inline void CMDIFrame::SetActiveMDIChild(CMDIChild* pChild)
+ {
+ assert ( pChild->IsWindow() );
+
+ GetMDIClient().SendMessage(WM_MDIACTIVATE, (WPARAM)pChild->GetHwnd(), 0L);
+
+ // Verify
+ assert ( m_hActiveMDIChild == pChild->GetHwnd() );
+ }
+
+ inline void CMDIFrame::UpdateCheckMarks()
+ {
+ if ((GetActiveMDIChild()) && GetActiveMDIChild()->m_hChildMenu)
+ {
+ HMENU hMenu = GetActiveMDIChild()->m_hChildMenu;
+
+ UINT uCheck = GetToolBar().IsWindowVisible()? MF_CHECKED : MF_UNCHECKED;
+ ::CheckMenuItem(hMenu, IDW_VIEW_TOOLBAR, uCheck);
+
+ uCheck = GetStatusBar().IsWindowVisible()? MF_CHECKED : MF_UNCHECKED;
+ ::CheckMenuItem (hMenu, IDW_VIEW_STATUSBAR, uCheck);
+ }
+ }
+
+ inline void CMDIFrame::UpdateFrameMenu(HMENU hMenu)
+ {
+ int nMenuItems = GetMenuItemCount(hMenu);
+ if (nMenuItems > 0)
+ {
+ // The Window menu is typically second from the right
+ int nWindowItem = MAX (nMenuItems -2, 0);
+ HMENU hMenuWindow = ::GetSubMenu (hMenu, nWindowItem);
+
+ if (hMenuWindow)
+ {
+ if (IsMenuBarUsed())
+ {
+ AppendMDIMenu(hMenuWindow);
+ GetMenuBar().SetMenu(hMenu);
+ }
+ else
+ {
+ GetView()->SendMessage (WM_MDISETMENU, (WPARAM) hMenu, (LPARAM)hMenuWindow);
+ DrawMenuBar();
+ }
+ }
+ }
+ UpdateCheckMarks();
+ }
+
+ inline LRESULT CMDIFrame::WndProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam)
+ {
+ switch (uMsg)
+ {
+ case WM_CLOSE:
+ OnClose();
+ return 0;
+
+ case WM_WINDOWPOSCHANGED:
+ // MDI Child or MDI frame has been resized
+ OnWindowPosChanged();
+ break; // Continue with default processing
+
+ } // switch uMsg
+ return CFrame::WndProcDefault(uMsg, wParam, lParam);
+ }
+
+ inline HWND CMDIFrame::CMDIClient::Create(CWnd* pParent)
+ {
+ assert(pParent != 0);
+
+ CLIENTCREATESTRUCT clientcreate ;
+ clientcreate.hWindowMenu = m_hWnd;
+ clientcreate.idFirstChild = IDW_FIRSTCHILD ;
+ DWORD dwStyle = WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | MDIS_ALLCHILDSTYLES;
+
+ // Create the view window
+ CreateEx(WS_EX_CLIENTEDGE, _T("MDICLient"), TEXT(""), dwStyle, 0, 0, 0, 0, pParent, NULL, (PSTR) &clientcreate);
+
+ return m_hWnd;
+ }
+
+ inline LRESULT CMDIFrame::CMDIClient::WndProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
+ {
+ switch (uMsg)
+ {
+ case WM_MDIDESTROY:
+ {
+ // Do default processing first
+ CallWindowProc(GetPrevWindowProc(), uMsg, wParam, lParam);
+
+ // Now remove MDI child
+ GetMDIFrame()->RemoveMDIChild((HWND) wParam);
+ }
+ return 0; // Discard message
+
+ case WM_MDISETMENU:
+ {
+ if (GetMDIFrame()->IsMenuBarUsed())
+ {
+ return 0L;
+ }
+ }
+ break;
+
+ case WM_MDIACTIVATE:
+ {
+ // Suppress redraw to avoid flicker when activating maximised MDI children
+ SendMessage(WM_SETREDRAW, FALSE, 0L);
+ LRESULT lr = CallWindowProc(GetPrevWindowProc(), WM_MDIACTIVATE, wParam, lParam);
+ SendMessage(WM_SETREDRAW, TRUE, 0L);
+ RedrawWindow(0, 0, RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN);
+
+ return lr;
+ }
+ }
+ return CWnd::WndProcDefault(uMsg, wParam, lParam);
+ }
+
+
+ /////////////////////////////////////
+ //Definitions for the CMDIChild class
+ //
+ inline CMDIChild::CMDIChild() : m_pView(NULL), m_hChildMenu(NULL)
+ {
+ // Set the MDI Child's menu and accelerator in the constructor, like this ...
+ // HMENU hChildMenu = LoadMenu(GetApp()->GetResourceHandle(), _T("MdiMenuView"));
+ // HACCEL hChildAccel = LoadAccelerators(GetApp()->GetResourceHandle(), _T("MDIAccelView"));
+ // SetHandles(hChildMenu, hChildAccel);
+ }
+
+ inline CMDIChild::~CMDIChild()
+ {
+ if (IsWindow())
+ GetParent()->SendMessage(WM_MDIDESTROY, (WPARAM)m_hWnd, 0L);
+
+ if (m_hChildMenu)
+ ::DestroyMenu(m_hChildMenu);
+ }
+
+ inline HWND CMDIChild::Create(CWnd* pParent /*= NULL*/)
+ // We create the MDI child window and then maximize if required.
+ // This technique avoids unnecessary flicker when creating maximized MDI children.
+ {
+ //Call PreCreate in case its overloaded
+ PreCreate(*m_pcs);
+
+ //Determine if the window should be created maximized
+ BOOL bMax = FALSE;
+ pParent->SendMessage(WM_MDIGETACTIVE, 0L, (LPARAM)&bMax);
+ bMax = bMax | (m_pcs->style & WS_MAXIMIZE);
+
+ // Set the Window Class Name
+ TCHAR szClassName[MAX_STRING_SIZE + 1] = _T("Win32++ MDI Child");
+ if (m_pcs->lpszClass)
+ lstrcpyn(szClassName, m_pcs->lpszClass, MAX_STRING_SIZE);
+
+ // Set the window style
+ DWORD dwStyle;
+ dwStyle = m_pcs->style & ~WS_MAXIMIZE;
+ dwStyle |= WS_VISIBLE | WS_OVERLAPPEDWINDOW ;
+
+ // Set window size and position
+ int x = CW_USEDEFAULT;
+ int y = CW_USEDEFAULT;
+ int cx = CW_USEDEFAULT;
+ int cy = CW_USEDEFAULT;
+ if(m_pcs->cx && m_pcs->cy)
+ {
+ x = m_pcs->x;
+ y = m_pcs->y;
+ cx = m_pcs->cx;
+ cy = m_pcs->cy;
+ }
+
+ // Set the extended style
+ DWORD dwExStyle = m_pcs->dwExStyle | WS_EX_MDICHILD;
+
+ // Turn off redraw while creating the window
+ pParent->SendMessage(WM_SETREDRAW, FALSE, 0L);
+
+ // Create the window
+ if (!CreateEx(dwExStyle, szClassName, m_pcs->lpszName, dwStyle, x, y,
+ cx, cy, pParent, FromHandle(m_pcs->hMenu), m_pcs->lpCreateParams))
+ throw CWinException(_T("CMDIChild::Create ... CreateEx failed"));
+
+ if (bMax)
+ ShowWindow(SW_MAXIMIZE);
+
+ // Turn redraw back on
+ pParent->SendMessage(WM_SETREDRAW, TRUE, 0L);
+ pParent->RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_ALLCHILDREN);
+
+ // Ensure bits revealed by round corners (XP themes) are redrawn
+ SetWindowPos(NULL, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE|SWP_FRAMECHANGED);
+
+ if (m_hChildMenu)
+ GetMDIFrame()->UpdateFrameMenu(m_hChildMenu);
+ if (m_hChildAccel)
+ GetApp()->SetAccelerators(m_hChildAccel, this);
+
+ return m_hWnd;
+ }
+
+ inline CMDIFrame* CMDIChild::GetMDIFrame() const
+ {
+ CMDIFrame* pMDIFrame = (CMDIFrame*)GetParent()->GetParent();
+ assert(dynamic_cast<CMDIFrame*>(pMDIFrame));
+ return pMDIFrame;
+ }
+
+ inline LRESULT CMDIChild::FinalWindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
+ {
+ return ::DefMDIChildProc(m_hWnd, uMsg, wParam, lParam);
+ }
+
+ inline void CMDIChild::MDIActivate() const
+ {
+ GetParent()->SendMessage(WM_MDIACTIVATE, (WPARAM)m_hWnd, 0L);
+ }
+
+ inline void CMDIChild::MDIDestroy() const
+ {
+ GetParent()->SendMessage(WM_MDIDESTROY, (WPARAM)m_hWnd, 0L);
+ }
+
+ inline void CMDIChild::MDIMaximize() const
+ {
+ GetParent()->SendMessage(WM_MDIMAXIMIZE, (WPARAM)m_hWnd, 0L);
+ }
+
+ inline void CMDIChild::MDIRestore() const
+ {
+ GetParent()->SendMessage(WM_MDIRESTORE, (WPARAM)m_hWnd, 0L);
+ }
+
+ inline void CMDIChild::OnCreate()
+ {
+ // Create the view window
+ assert(GetView()); // Use SetView in CMDIChild's constructor to set the view window
+ GetView()->Create(this);
+ RecalcLayout();
+ }
+
+ inline void CMDIChild::RecalcLayout()
+ {
+ // Resize the View window
+ CRect rc = GetClientRect();
+ m_pView->SetWindowPos( NULL, rc.left, rc.top, rc.Width(), rc.Height(), SWP_SHOWWINDOW );
+ }
+
+ inline void CMDIChild::SetHandles(HMENU hMenu, HACCEL hAccel)
+ {
+ m_hChildMenu = hMenu;
+ m_hChildAccel = hAccel;
+
+ // Note: It is valid to call SetChildMenu before the window is created
+ if (IsWindow())
+ {
+ CWnd* pWnd = GetMDIFrame()->GetActiveMDIChild();
+ if (pWnd == this)
+ {
+ if (m_hChildMenu)
+ GetMDIFrame()->UpdateFrameMenu(m_hChildMenu);
+
+ if (m_hChildAccel)
+ GetApp()->SetAccelerators(m_hChildAccel, GetMDIFrame());
+ }
+ }
+ }
+
+ inline void CMDIChild::SetView(CWnd& wndView)
+ // Sets or changes the View window displayed within the frame
+ {
+ if (m_pView != &wndView)
+ {
+ // Destroy the existing view window (if any)
+ if (m_pView) m_pView->Destroy();
+
+ // Assign the view window
+ m_pView = &wndView;
+
+ if (m_hWnd)
+ {
+ // The frame is already created, so create and position the new view too
+ assert(GetView()); // Use SetView in CMDIChild's constructor to set the view window
+ GetView()->Create(this);
+ RecalcLayout();
+ }
+ }
+ }
+
+ inline LRESULT CMDIChild::WndProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam)
+ {
+ switch (uMsg)
+ {
+ case WM_MDIACTIVATE:
+ {
+ // This child is being activated
+ if (lParam == (LPARAM) m_hWnd)
+ {
+ GetMDIFrame()->m_hActiveMDIChild = m_hWnd;
+ // Set the menu to child default menu
+ if (m_hChildMenu)
+ GetMDIFrame()->UpdateFrameMenu(m_hChildMenu);
+ if (m_hChildAccel)
+ GetApp()->SetAccelerators(m_hChildAccel, this);
+ }
+
+ // No child is being activated
+ if (0 == lParam)
+ {
+ GetMDIFrame()->m_hActiveMDIChild = NULL;
+ // Set the menu to frame's original menu
+ GetMDIFrame()->UpdateFrameMenu(GetMDIFrame()->GetFrameMenu());
+ GetApp()->SetAccelerators(GetMDIFrame()->GetFrameAccel(), this);
+ }
+ }
+ return 0L ;
+
+ case WM_WINDOWPOSCHANGED:
+ {
+ RecalcLayout();
+ break;
+ }
+ }
+ return CWnd::WndProcDefault(uMsg, wParam, lParam);
+ }
+
+
+} // namespace Win32xx
+
+#endif // _WIN32XX_MDI_H_
+
diff --git a/mmc_updater/depends/win32cpp/menu.h b/mmc_updater/depends/win32cpp/menu.h
new file mode 100644
index 00000000..136bafa3
--- /dev/null
+++ b/mmc_updater/depends/win32cpp/menu.h
@@ -0,0 +1,600 @@
+// Win32++ Version 7.2
+// Released: 5th AUgust 2011
+//
+// David Nash
+// email: dnash@bigpond.net.au
+// url: https://sourceforge.net/projects/win32-framework
+//
+//
+// Copyright (c) 2005-2011 David Nash
+//
+// Permission is hereby granted, free of charge, to
+// any person obtaining a copy of this software and
+// associated documentation files (the "Software"),
+// to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify,
+// merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom
+// the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice
+// shall be included in all copies or substantial portions
+// of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
+// OR OTHER DEALINGS IN THE SOFTWARE.
+//
+////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////
+// menu.h
+// Declaration of the CMenu class
+
+// Notes
+// 1) Owner-drawn menus send the WM_MEASUREITEM and WM_DRAWITEM messages
+// to the window that owns the menu. To manage owner drawing for menus,
+// handle these two messages in the CWnd's WndProc function.
+//
+// 2) The CMenu pointer returned by FromHandle might be a temporary pointer. It
+// should be used immediately, not saved for later use.
+//
+// 3) The CMenu pointers returned by FromHandle or GetSubMenu do not need
+// to be deleted. They are automatically deleted by the Win32++.
+//
+// 4) CMenu pointers returned by GetSubMenu are deleted when the parent CMenu is
+// detached, destroyed or deconstructed.
+//
+// 5) The HMENU that is attached to a CMenu object (using the attach function) is
+// automatically deleted when the CMenu object goes out of scope. Detach the
+// HMENU to stop it being deleted when CMenu's destructor is called.
+//
+// 6) Pass CMenu objects by reference or by pointer when passing them as function
+// arguments.
+//
+// 7) In those functions that use a MENUITEMINFO structure, its cbSize member is
+// automatically set to the correct value.
+
+// Program sample
+// --------------
+// void CView::CreatePopup()
+// {
+// CPoint pt = GetCursorPos();
+//
+// // Create the menu
+// CMenu Popup;
+// Popup.CreatePopupMenu();
+//
+// // Add some menu items
+// Popup.AppendMenu(MF_STRING, 101, _T("Menu Item &1"));
+// Popup.AppendMenu(MF_STRING, 102, _T("Menu Item &2"));
+// Popup.AppendMenu(MF_STRING, 103, _T("Menu Item &3"));
+// Popup.AppendMenu(MF_SEPARATOR);
+// Popup.AppendMenu(MF_STRING, 104, _T("Menu Item &4"));
+//
+// // Set menu item states
+// Popup.CheckMenuRadioItem(101, 101, 101, MF_BYCOMMAND);
+// Popup.CheckMenuItem(102, MF_BYCOMMAND | MF_CHECKED);
+// Popup.EnableMenuItem(103, MF_BYCOMMAND | MF_GRAYED);
+// Popup.SetDefaultItem(104);
+//
+// // Display the popup menu
+// Popup.TrackPopupMenu(0, pt.x, pt.y, this);
+// }
+
+
+
+#if !defined(_WIN32XX_MENU_H_) && !defined(_WIN32_WCE)
+#define _WIN32XX_MENU_H_
+
+
+#include "wincore.h"
+#include "gdi.h"
+
+
+namespace Win32xx
+{
+
+ // Forward declarations
+ class CBitmap;
+
+ class CMenu
+ {
+ friend class CWinApp;
+
+ public:
+ //Construction
+ CMenu() : m_hMenu(0), m_IsTmpMenu(FALSE) {}
+ CMenu(UINT nID) : m_IsTmpMenu(FALSE)
+ {
+ m_hMenu = ::LoadMenu(GetApp()->GetResourceHandle(), MAKEINTRESOURCE(nID));
+ }
+ ~CMenu();
+
+ //Initialization
+ void Attach(HMENU hMenu);
+ void CreateMenu();
+ void CreatePopupMenu();
+ void DestroyMenu();
+ HMENU Detach();
+ HMENU GetHandle() const;
+ BOOL LoadMenu(LPCTSTR lpszResourceName);
+ BOOL LoadMenu(UINT uIDResource);
+ BOOL LoadMenuIndirect(const void* lpMenuTemplate);
+
+ //Menu Operations
+ BOOL TrackPopupMenu(UINT uFlags, int x, int y, CWnd* pWnd, LPCRECT lpRect = 0);
+ BOOL TrackPopupMenuEx(UINT uFlags, int x, int y, CWnd* pWnd, LPTPMPARAMS lptpm);
+
+ //Menu Item Operations
+ BOOL AppendMenu(UINT uFlags, UINT_PTR uIDNewItem = 0, LPCTSTR lpszNewItem = NULL);
+ BOOL AppendMenu(UINT uFlags, UINT_PTR uIDNewItem, const CBitmap* pBmp);
+ UINT CheckMenuItem(UINT uIDCheckItem, UINT uCheck);
+ BOOL CheckMenuRadioItem(UINT uIDFirst, UINT uIDLast, UINT uIDItem, UINT uFlags);
+ BOOL DeleteMenu(UINT uPosition, UINT uFlags);
+ UINT EnableMenuItem(UINT uIDEnableItem, UINT uEnable);
+ UINT GetDefaultItem(UINT gmdiFlags, BOOL fByPos = FALSE);
+ DWORD GetMenuContextHelpId() const;
+
+#if(WINVER >= 0x0500) // Minimum OS required is Win2000
+ BOOL GetMenuInfo(LPMENUINFO lpcmi) const;
+ BOOL SetMenuInfo(LPCMENUINFO lpcmi);
+#endif
+
+ UINT GetMenuItemCount() const;
+ UINT GetMenuItemID(int nPos) const;
+ BOOL GetMenuItemInfo(UINT uItem, LPMENUITEMINFO lpMenuItemInfo, BOOL fByPos = FALSE);
+ UINT GetMenuState(UINT uID, UINT uFlags) const;
+ int GetMenuString(UINT uIDItem, LPTSTR lpString, int nMaxCount, UINT uFlags) const;
+ int GetMenuString(UINT uIDItem, CString& rString, UINT uFlags) const;
+ CMenu* GetSubMenu(int nPos);
+ BOOL InsertMenu(UINT uPosition, UINT uFlags, UINT_PTR uIDNewItem = 0, LPCTSTR lpszNewItem = NULL);
+ BOOL InsertMenu(UINT uPosition, UINT uFlags, UINT_PTR uIDNewItem, const CBitmap* pBmp);
+ BOOL InsertMenuItem(UINT uItem, LPMENUITEMINFO lpMenuItemInfo, BOOL fByPos = FALSE);
+ BOOL ModifyMenu(UINT uPosition, UINT uFlags, UINT_PTR uIDNewItem = 0, LPCTSTR lpszNewItem = NULL);
+ BOOL ModifyMenu(UINT uPosition, UINT uFlags, UINT_PTR uIDNewItem, const CBitmap* pBmp);
+ BOOL RemoveMenu(UINT uPosition, UINT uFlags);
+ BOOL SetDefaultItem(UINT uItem, BOOL fByPos = FALSE);
+ BOOL SetMenuContextHelpId(DWORD dwContextHelpId);
+ BOOL SetMenuItemBitmaps(UINT uPosition, UINT uFlags, const CBitmap* pBmpUnchecked, const CBitmap* pBmpChecked);
+ BOOL SetMenuItemInfo(UINT uItem, LPMENUITEMINFO lpMenuItemInfo, BOOL fByPos = FALSE);
+
+ //Operators
+ BOOL operator != (const CMenu& menu) const;
+ BOOL operator == (const CMenu& menu) const;
+ operator HMENU () const;
+
+ private:
+ CMenu(const CMenu&); // Disable copy construction
+ CMenu& operator = (const CMenu&); // Disable assignment operator
+ void AddToMap();
+ BOOL RemoveFromMap();
+ std::vector<MenuPtr> m_vSubMenus; // A vector of smart pointers to CMenu
+ HMENU m_hMenu;
+ BOOL m_IsTmpMenu;
+ };
+
+ inline CMenu::~CMenu()
+ {
+ if (m_hMenu)
+ {
+ if (!m_IsTmpMenu)
+ {
+ ::DestroyMenu(m_hMenu);
+ }
+
+ RemoveFromMap();
+ }
+
+ m_vSubMenus.clear();
+ }
+
+ inline void CMenu::AddToMap()
+ // Store the HMENU and CMenu pointer in the HMENU map
+ {
+ assert( GetApp() );
+ assert(m_hMenu);
+
+ GetApp()->m_csMapLock.Lock();
+ GetApp()->m_mapHMENU.insert(std::make_pair(m_hMenu, this));
+ GetApp()->m_csMapLock.Release();
+ }
+
+ inline BOOL CMenu::RemoveFromMap()
+ {
+ BOOL Success = FALSE;
+
+ if (GetApp())
+ {
+ // Allocate an iterator for our HDC map
+ std::map<HMENU, CMenu*, CompareHMENU>::iterator m;
+
+ CWinApp* pApp = GetApp();
+ if (pApp)
+ {
+ // Erase the CDC pointer entry from the map
+ pApp->m_csMapLock.Lock();
+ for (m = pApp->m_mapHMENU.begin(); m != pApp->m_mapHMENU.end(); ++m)
+ {
+ if (this == m->second)
+ {
+ pApp->m_mapHMENU.erase(m);
+ Success = TRUE;
+ break;
+ }
+ }
+
+ pApp->m_csMapLock.Release();
+ }
+ }
+
+ return Success;
+ }
+
+
+ inline BOOL CMenu::AppendMenu(UINT uFlags, UINT_PTR uIDNewItem /*= 0*/, LPCTSTR lpszNewItem /*= NULL*/)
+ // Appends a new item to the end of the specified menu bar, drop-down menu, submenu, or shortcut menu.
+ {
+ assert(IsMenu(m_hMenu));
+ return ::AppendMenu(m_hMenu, uFlags, uIDNewItem, lpszNewItem);
+ }
+
+ inline BOOL CMenu::AppendMenu(UINT uFlags, UINT_PTR uIDNewItem, const CBitmap* pBmp)
+ // Appends a new item to the end of the specified menu bar, drop-down menu, submenu, or shortcut menu.
+ {
+ assert(IsMenu(m_hMenu));
+ assert(pBmp);
+ return ::AppendMenu(m_hMenu, uFlags, uIDNewItem, (LPCTSTR)pBmp->GetHandle());
+ }
+
+ inline void CMenu::Attach(HMENU hMenu)
+ // Attaches an existing menu to this CMenu
+ {
+ if (m_hMenu != NULL && m_hMenu != hMenu)
+ {
+ ::DestroyMenu(Detach());
+ }
+
+ if (hMenu)
+ {
+ m_hMenu = hMenu;
+ AddToMap();
+ }
+ }
+
+ inline UINT CMenu::CheckMenuItem(UINT uIDCheckItem, UINT uCheck)
+ // Sets the state of the specified menu item's check-mark attribute to either selected or clear.
+ {
+ assert(IsMenu(m_hMenu));
+ return ::CheckMenuItem(m_hMenu, uIDCheckItem, uCheck);
+ }
+
+ inline BOOL CMenu::CheckMenuRadioItem(UINT uIDFirst, UINT uIDLast, UINT uIDItem, UINT uFlags)
+ // Checks a specified menu item and makes it a radio item. At the same time, the function clears
+ // all other menu items in the associated group and clears the radio-item type flag for those items.
+ {
+ assert(IsMenu(m_hMenu));
+ return ::CheckMenuRadioItem(m_hMenu, uIDFirst, uIDLast, uIDItem, uFlags);
+ }
+
+ inline void CMenu::CreateMenu()
+ // Creates an empty menu.
+ {
+ assert(NULL == m_hMenu);
+ m_hMenu = ::CreateMenu();
+ AddToMap();
+ }
+
+ inline void CMenu::CreatePopupMenu()
+ // Creates a drop-down menu, submenu, or shortcut menu. The menu is initially empty.
+ {
+ assert(NULL == m_hMenu);
+ m_hMenu = ::CreatePopupMenu();
+ AddToMap();
+ }
+
+ inline BOOL CMenu::DeleteMenu(UINT uPosition, UINT uFlags)
+ // Deletes an item from the specified menu.
+ {
+ assert(IsMenu(m_hMenu));
+ return ::DeleteMenu(m_hMenu, uPosition, uFlags);
+ }
+
+ inline void CMenu::DestroyMenu()
+ // Destroys the menu and frees any memory that the menu occupies.
+ {
+ if (::IsMenu(m_hMenu))
+ ::DestroyMenu(m_hMenu);
+
+ m_hMenu = 0;
+ RemoveFromMap();
+ m_vSubMenus.clear();
+ }
+
+ inline HMENU CMenu::Detach()
+ // Detaches the HMENU from this CMenu. If the HMENU is not detached it will be
+ // destroyed when this CMenu is deconstructed.
+ {
+ assert(IsMenu(m_hMenu));
+ HMENU hMenu = m_hMenu;
+ m_hMenu = 0;
+ RemoveFromMap();
+ m_vSubMenus.clear();
+ return hMenu;
+ }
+
+ inline HMENU CMenu::GetHandle() const
+ // Returns the HMENU assigned to this CMenu
+ {
+ return m_hMenu;
+ }
+
+ inline UINT CMenu::EnableMenuItem(UINT uIDEnableItem, UINT uEnable)
+ // Enables, disables, or grays the specified menu item.
+ // The uEnable parameter must be a combination of either MF_BYCOMMAND or MF_BYPOSITION
+ // and MF_ENABLED, MF_DISABLED, or MF_GRAYED.
+ {
+ assert(IsMenu(m_hMenu));
+ return ::EnableMenuItem(m_hMenu, uIDEnableItem, uEnable);
+ }
+
+ inline UINT CMenu::GetDefaultItem(UINT gmdiFlags, BOOL fByPos /*= FALSE*/)
+ // Determines the default menu item.
+ // The gmdiFlags parameter specifies how the function searches for menu items.
+ // This parameter can be zero or more of the following values: GMDI_GOINTOPOPUPS; GMDI_USEDISABLED.
+ {
+ assert(IsMenu(m_hMenu));
+ return ::GetMenuDefaultItem(m_hMenu, fByPos, gmdiFlags);
+ }
+
+ inline DWORD CMenu::GetMenuContextHelpId() const
+ // Retrieves the Help context identifier associated with the menu.
+ {
+ assert(IsMenu(m_hMenu));
+ return ::GetMenuContextHelpId(m_hMenu);
+ }
+
+#if(WINVER >= 0x0500)
+// minimum OS required : Win2000
+
+ inline BOOL CMenu::GetMenuInfo(LPMENUINFO lpcmi) const
+ // Retrieves the menu information.
+ {
+ assert(IsMenu(m_hMenu));
+ return ::GetMenuInfo(m_hMenu, lpcmi);
+ }
+
+ inline BOOL CMenu::SetMenuInfo(LPCMENUINFO lpcmi)
+ // Sets the menu information from the specified MENUINFO structure.
+ {
+ assert(IsMenu(m_hMenu));
+ return ::SetMenuInfo(m_hMenu, lpcmi);
+ }
+
+#endif
+
+ inline UINT CMenu::GetMenuItemCount() const
+ // Retrieves the number of menu items.
+ {
+ assert(IsMenu(m_hMenu));
+ return ::GetMenuItemCount(m_hMenu);
+ }
+
+ inline UINT CMenu::GetMenuItemID(int nPos) const
+ // Retrieves the menu item identifier of a menu item located at the specified position
+ {
+ assert(IsMenu(m_hMenu));
+ return ::GetMenuItemID(m_hMenu, nPos);
+ }
+
+ inline BOOL CMenu::GetMenuItemInfo(UINT uItem, LPMENUITEMINFO lpMenuItemInfo, BOOL fByPos /*= FALSE*/)
+ // retrieves information about the specified menu item.
+ {
+ assert(IsMenu(m_hMenu));
+ assert(lpMenuItemInfo);
+ lpMenuItemInfo->cbSize = GetSizeofMenuItemInfo();
+ return ::GetMenuItemInfo(m_hMenu, uItem, fByPos, lpMenuItemInfo);
+ }
+
+ inline UINT CMenu::GetMenuState(UINT uID, UINT uFlags) const
+ // Retrieves the menu flags associated with the specified menu item.
+ // Possible values for uFlags are: MF_BYCOMMAND (default) or MF_BYPOSITION.
+ {
+ assert(IsMenu(m_hMenu));
+ return ::GetMenuState(m_hMenu, uID, uFlags);
+ }
+
+ inline int CMenu::GetMenuString(UINT uIDItem, LPTSTR lpString, int nMaxCount, UINT uFlags) const
+ // Copies the text string of the specified menu item into the specified buffer.
+ {
+ assert(IsMenu(m_hMenu));
+ assert(lpString);
+ return ::GetMenuString(m_hMenu, uIDItem, lpString, nMaxCount, uFlags);
+ }
+
+ inline int CMenu::GetMenuString(UINT uIDItem, CString& rString, UINT uFlags) const
+ // Copies the text string of the specified menu item into the specified buffer.
+ {
+ assert(IsMenu(m_hMenu));
+ return ::GetMenuString(m_hMenu, uIDItem, (LPTSTR)rString.c_str(), rString.GetLength(), uFlags);
+ }
+
+ inline CMenu* CMenu::GetSubMenu(int nPos)
+ // Retrieves the CMenu object of a pop-up menu.
+ {
+ assert(IsMenu(m_hMenu));
+ CMenu* pMenu = new CMenu;
+ pMenu->m_hMenu = ::GetSubMenu(m_hMenu, nPos);
+ pMenu->m_IsTmpMenu = TRUE;
+ m_vSubMenus.push_back(pMenu);
+ return pMenu;
+ }
+
+ inline BOOL CMenu::InsertMenu(UINT uPosition, UINT uFlags, UINT_PTR uIDNewItem /*= 0*/, LPCTSTR lpszNewItem /*= NULL*/)
+ // Inserts a new menu item into a menu, moving other items down the menu.
+ {
+ assert(IsMenu(m_hMenu));
+ return ::InsertMenu(m_hMenu, uPosition, uFlags, uIDNewItem, lpszNewItem);
+ }
+
+ inline BOOL CMenu::InsertMenu(UINT uPosition, UINT uFlags, UINT_PTR uIDNewItem, const CBitmap* pBmp)
+ // Inserts a new menu item into a menu, moving other items down the menu.
+ {
+ assert(IsMenu(m_hMenu));
+ return ::InsertMenu(m_hMenu, uPosition, uFlags, uIDNewItem, (LPCTSTR)pBmp->GetHandle());
+ }
+
+ inline BOOL CMenu::InsertMenuItem(UINT uItem, LPMENUITEMINFO lpMenuItemInfo, BOOL fByPos /*= FALSE*/)
+ // Inserts a new menu item at the specified position in a menu.
+ {
+ assert(IsMenu(m_hMenu));
+ assert(lpMenuItemInfo);
+ lpMenuItemInfo->cbSize = GetSizeofMenuItemInfo();
+ return ::InsertMenuItem(m_hMenu, uItem, fByPos, lpMenuItemInfo);
+ }
+
+ inline BOOL CMenu::LoadMenu(LPCTSTR lpszResourceName)
+ // Loads the menu from the specified windows resource.
+ {
+ assert(NULL == m_hMenu);
+ assert(lpszResourceName);
+ m_hMenu = ::LoadMenu(GetApp()->GetResourceHandle(), lpszResourceName);
+ if (m_hMenu) AddToMap();
+ return NULL != m_hMenu;
+ }
+
+ inline BOOL CMenu::LoadMenu(UINT uIDResource)
+ // Loads the menu from the specified windows resource.
+ {
+ assert(NULL == m_hMenu);
+ m_hMenu = ::LoadMenu(GetApp()->GetResourceHandle(), MAKEINTRESOURCE(uIDResource));
+ if (m_hMenu) AddToMap();
+ return NULL != m_hMenu;
+ }
+
+ inline BOOL CMenu::LoadMenuIndirect(const void* lpMenuTemplate)
+ // Loads the specified menu template and assigns it to this CMenu.
+ {
+ assert(NULL == m_hMenu);
+ assert(lpMenuTemplate);
+ m_hMenu = ::LoadMenuIndirect(lpMenuTemplate);
+ if (m_hMenu) AddToMap();
+ return NULL != m_hMenu;
+ }
+
+ inline BOOL CMenu::ModifyMenu(UINT uPosition, UINT uFlags, UINT_PTR uIDNewItem /*= 0*/, LPCTSTR lpszNewItem /*= NULL*/)
+ // Changes an existing menu item. This function is used to specify the content, appearance, and behavior of the menu item.
+ {
+ assert(IsMenu(m_hMenu));
+ return ::ModifyMenu(m_hMenu, uPosition, uFlags, uIDNewItem, lpszNewItem);
+ }
+
+ inline BOOL CMenu::ModifyMenu(UINT uPosition, UINT uFlags, UINT_PTR uIDNewItem, const CBitmap* pBmp)
+ // Changes an existing menu item. This function is used to specify the content, appearance, and behavior of the menu item.
+ {
+ assert(IsMenu(m_hMenu));
+ assert(pBmp);
+ return ::ModifyMenu(m_hMenu, uPosition, uFlags, uIDNewItem, (LPCTSTR)pBmp->GetHandle());
+ }
+
+ inline BOOL CMenu::RemoveMenu(UINT uPosition, UINT uFlags)
+ // Deletes a menu item or detaches a submenu from the menu.
+ {
+ assert(IsMenu(m_hMenu));
+ return ::RemoveMenu(m_hMenu, uPosition, uFlags);
+ }
+
+ inline BOOL CMenu::SetDefaultItem(UINT uItem, BOOL fByPos /*= FALSE*/)
+ // sets the default menu item for the menu.
+ {
+ assert(IsMenu(m_hMenu));
+ return ::SetMenuDefaultItem(m_hMenu, uItem, fByPos);
+ }
+
+ inline BOOL CMenu::SetMenuContextHelpId(DWORD dwContextHelpId)
+ // Associates a Help context identifier with the menu.
+ {
+ assert(IsMenu(m_hMenu));
+ return ::SetMenuContextHelpId(m_hMenu, dwContextHelpId);
+ }
+
+ inline BOOL CMenu::SetMenuItemBitmaps(UINT uPosition, UINT uFlags, const CBitmap* pBmpUnchecked, const CBitmap* pBmpChecked)
+ // Associates the specified bitmap with a menu item.
+ {
+ assert(IsMenu(m_hMenu));
+ return ::SetMenuItemBitmaps(m_hMenu, uPosition, uFlags, *pBmpUnchecked, *pBmpChecked);
+ }
+
+ inline BOOL CMenu::SetMenuItemInfo(UINT uItem, LPMENUITEMINFO lpMenuItemInfo, BOOL fByPos /*= FALSE*/)
+ // Changes information about a menu item.
+ {
+ assert(IsMenu(m_hMenu));
+ assert(lpMenuItemInfo);
+ lpMenuItemInfo->cbSize = GetSizeofMenuItemInfo();
+ return ::SetMenuItemInfo(m_hMenu, uItem, fByPos, lpMenuItemInfo);
+ }
+
+ inline BOOL CMenu::TrackPopupMenu(UINT uFlags, int x, int y, CWnd* pWnd, LPCRECT lpRect /*= 0*/)
+ // Displays a shortcut menu at the specified location and tracks the selection of items on the menu.
+ {
+ assert(IsMenu(m_hMenu));
+ HWND hWnd = pWnd? pWnd->GetHwnd() : 0;
+ return ::TrackPopupMenu(m_hMenu, uFlags, x, y, 0, hWnd, lpRect);
+ }
+
+ inline BOOL CMenu::TrackPopupMenuEx(UINT uFlags, int x, int y, CWnd* pWnd, LPTPMPARAMS lptpm)
+ // Displays a shortcut menu at the specified location and tracks the selection of items on the shortcut menu.
+ {
+ assert(IsMenu(m_hMenu));
+ HWND hWnd = pWnd? pWnd->GetHwnd() : 0;
+ return ::TrackPopupMenuEx(m_hMenu, uFlags, x, y, hWnd, lptpm);
+ }
+
+ inline BOOL CMenu::operator != (const CMenu& menu) const
+ // Returns TRUE if the two menu objects are not equal.
+ {
+ return menu.m_hMenu != m_hMenu;
+ }
+
+ inline BOOL CMenu::operator == (const CMenu& menu) const
+ // Returns TRUE of the two menu object are equal
+ {
+ return menu.m_hMenu == m_hMenu;
+ }
+
+ inline CMenu::operator HMENU () const
+ // Retrieves the menu's handle.
+ {
+ return m_hMenu;
+ }
+
+
+ ///////////////////////////////////////
+ // Global functions
+ //
+
+ inline CMenu* FromHandle(HMENU hMenu)
+ // Returns the CMenu object associated with the menu handle (HMENU).
+ {
+ assert( GetApp() );
+ CMenu* pMenu = GetApp()->GetCMenuFromMap(hMenu);
+ if (::IsMenu(hMenu) && pMenu == 0)
+ {
+ GetApp()->AddTmpMenu(hMenu);
+ pMenu = GetApp()->GetCMenuFromMap(hMenu);
+ }
+ return pMenu;
+ }
+
+} // namespace Win32xx
+
+#endif // _WIN32XX_MENU_H_
+
diff --git a/mmc_updater/depends/win32cpp/propertysheet.h b/mmc_updater/depends/win32cpp/propertysheet.h
new file mode 100644
index 00000000..4048942c
--- /dev/null
+++ b/mmc_updater/depends/win32cpp/propertysheet.h
@@ -0,0 +1,960 @@
+// Win32++ Version 7.2
+// Released: 5th AUgust 2011
+//
+// David Nash
+// email: dnash@bigpond.net.au
+// url: https://sourceforge.net/projects/win32-framework
+//
+//
+// Copyright (c) 2005-2011 David Nash
+//
+// Permission is hereby granted, free of charge, to
+// any person obtaining a copy of this software and
+// associated documentation files (the "Software"),
+// to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify,
+// merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom
+// the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice
+// shall be included in all copies or substantial portions
+// of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
+// OR OTHER DEALINGS IN THE SOFTWARE.
+//
+////////////////////////////////////////////////////////
+
+
+///////////////////////////////////////////////////////
+// propertysheet.h
+// Declaration of the following classes:
+// CPropertyPage and CPropertySheet
+
+// These classes add support for property sheets to Win32++. A property sheet
+// will have one or more property pages. These pages are much like dialogs
+// which are presented within a tabbed dialog or within a wizard. The data
+// on a property page can be validated before the next page is presented.
+// Property sheets have three modes of use: Modal, Modeless, and Wizard.
+//
+// Refer to the PropertySheet demo program for an example of how propert sheets
+// can be used.
+
+
+#ifndef _WIN32XX_PROPERTYSHEET_H_
+#define _WIN32XX_PROPERTYSHEET_H_
+
+#include "dialog.h"
+
+#define ID_APPLY_NOW 0x3021
+#define ID_WIZBACK 0x3023
+#define ID_WIZNEXT 0x3024
+#define ID_WIZFINISH 0x3025
+#define ID_HELP 0xE146
+
+#ifndef PROPSHEETHEADER_V1_SIZE
+ #define PROPSHEETHEADER_V1_SIZE 40
+#endif
+
+namespace Win32xx
+{
+ class CPropertyPage;
+ typedef Shared_Ptr<CPropertyPage> PropertyPagePtr;
+
+ class CPropertyPage : public CWnd
+ {
+ public:
+ CPropertyPage (UINT nIDTemplate, LPCTSTR szTitle = NULL);
+ virtual ~CPropertyPage() {}
+
+ virtual INT_PTR DialogProc(UINT uMsg, WPARAM wParam, LPARAM lParam);
+ virtual INT_PTR DialogProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam);
+ virtual int OnApply();
+ virtual void OnCancel();
+ virtual void OnHelp();
+ virtual BOOL OnInitDialog();
+ virtual BOOL OnKillActive();
+ virtual LRESULT OnNotify(WPARAM wParam, LPARAM lParam);
+ virtual int OnOK();
+ virtual BOOL OnQueryCancel();
+ virtual BOOL OnQuerySiblings(WPARAM wParam, LPARAM lParam);
+ virtual int OnSetActive();
+ virtual int OnWizardBack();
+ virtual INT_PTR OnWizardFinish();
+ virtual int OnWizardNext();
+ virtual BOOL PreTranslateMessage(MSG* pMsg);
+
+ static UINT CALLBACK StaticPropSheetPageProc(HWND hwnd, UINT uMsg, LPPROPSHEETPAGE ppsp);
+ static INT_PTR CALLBACK StaticDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
+
+ void CancelToClose() const;
+ PROPSHEETPAGE GetPSP() const {return m_PSP;}
+ BOOL IsButtonEnabled(int iButton) const;
+ LRESULT QuerySiblings(WPARAM wParam, LPARAM lParam) const;
+ void SetModified(BOOL bChanged) const;
+ void SetTitle(LPCTSTR szTitle);
+ void SetWizardButtons(DWORD dwFlags) const;
+
+ protected:
+ PROPSHEETPAGE m_PSP;
+
+ private:
+ CPropertyPage(const CPropertyPage&); // Disable copy construction
+ CPropertyPage& operator = (const CPropertyPage&); // Disable assignment operator
+
+ tString m_Title;
+ };
+
+ class CPropertySheet : public CWnd
+ {
+ public:
+ CPropertySheet(UINT nIDCaption, CWnd* pParent = NULL);
+ CPropertySheet(LPCTSTR pszCaption = NULL, CWnd* pParent = NULL);
+ virtual ~CPropertySheet() {}
+
+ // Operations
+ virtual CPropertyPage* AddPage(CPropertyPage* pPage);
+ virtual HWND Create(CWnd* pParent = 0);
+ virtual INT_PTR CreatePropertySheet(LPCPROPSHEETHEADER ppsph);
+ virtual void DestroyButton(int iButton);
+ virtual void Destroy();
+ virtual int DoModal();
+ virtual void RemovePage(CPropertyPage* pPage);
+
+ // State functions
+ BOOL IsModeless() const;
+ BOOL IsWizard() const;
+
+ //Attributes
+ CPropertyPage* GetActivePage() const;
+ int GetPageCount() const;
+ int GetPageIndex(CPropertyPage* pPage) const;
+ HWND GetTabControl() const;
+ virtual BOOL SetActivePage(int nPage);
+ virtual BOOL SetActivePage(CPropertyPage* pPage);
+ virtual void SetIcon(UINT idIcon);
+ virtual void SetTitle(LPCTSTR szTitle);
+ virtual void SetWizardMode(BOOL bWizard);
+
+ protected:
+ virtual BOOL PreTranslateMessage(MSG* pMsg);
+ virtual LRESULT WndProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam);
+
+ private:
+ CPropertySheet(const CPropertySheet&); // Disable copy construction
+ CPropertySheet& operator = (const CPropertySheet&); // Disable assignment operator
+ void BuildPageArray();
+ static void CALLBACK Callback(HWND hwnd, UINT uMsg, LPARAM lParam);
+
+ tString m_Title;
+ std::vector<PropertyPagePtr> m_vPages; // vector of CPropertyPage
+ std::vector<PROPSHEETPAGE> m_vPSP; // vector of PROPSHEETPAGE
+ BOOL m_bInitialUpdate;
+ PROPSHEETHEADER m_PSH;
+ };
+
+}
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
+
+namespace Win32xx
+{
+
+ //////////////////////////////////////////
+ // Definitions for the CPropertyPage class
+ //
+ inline CPropertyPage::CPropertyPage(UINT nIDTemplate, LPCTSTR szTitle /* = NULL*/)
+ {
+ ZeroMemory(&m_PSP, sizeof(PROPSHEETPAGE));
+ SetTitle(szTitle);
+
+ m_PSP.dwSize = sizeof(PROPSHEETPAGE);
+ m_PSP.dwFlags |= PSP_USECALLBACK;
+ m_PSP.hInstance = GetApp()->GetResourceHandle();
+ m_PSP.pszTemplate = MAKEINTRESOURCE(nIDTemplate);
+ m_PSP.pszTitle = m_Title.c_str();
+ m_PSP.pfnDlgProc = (DLGPROC)CPropertyPage::StaticDialogProc;
+ m_PSP.lParam = (LPARAM)this;
+ m_PSP.pfnCallback = CPropertyPage::StaticPropSheetPageProc;
+ }
+
+ inline void CPropertyPage::CancelToClose() const
+ // Disables the Cancel button and changes the text of the OK button to "Close."
+ {
+ assert(::IsWindow(m_hWnd));
+ SendMessage(PSM_CANCELTOCLOSE, 0L, 0L);
+ }
+
+
+ inline INT_PTR CPropertyPage::DialogProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
+ {
+ // Override this function in your class derrived from CPropertyPage if you wish to handle messages
+ // A typical function might look like this:
+
+ // switch (uMsg)
+ // {
+ // case MESSAGE1: // Some Win32 API message
+ // OnMessage1(); // A user defined function
+ // break; // Also do default processing
+ // case MESSAGE2:
+ // OnMessage2();
+ // return x; // Don't do default processing, but instead return
+ // // a value recommended by the Win32 API documentation
+ // }
+
+ // Always pass unhandled messages on to DialogProcDefault
+ return DialogProcDefault(uMsg, wParam, lParam);
+ }
+
+ inline INT_PTR CPropertyPage::DialogProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam)
+ // All DialogProc functions should pass unhandled messages to this function
+ {
+ LRESULT lr = 0L;
+
+ switch (uMsg)
+ {
+ case UWM_CLEANUPTEMPS:
+ {
+ TLSData* pTLSData = (TLSData*)TlsGetValue(GetApp()->GetTlsIndex());
+ pTLSData->vTmpWnds.clear();
+ }
+ break;
+
+ case WM_INITDIALOG:
+ return OnInitDialog();
+
+ case PSM_QUERYSIBLINGS:
+ return (BOOL)OnQuerySiblings(wParam, lParam);
+
+ case WM_COMMAND:
+ {
+ // Refelect this message if it's from a control
+ CWnd* pWnd = GetApp()->GetCWndFromMap((HWND)lParam);
+ if (pWnd != NULL)
+ lr = pWnd->OnCommand(wParam, lParam);
+
+ // Handle user commands
+ if (!lr)
+ lr = OnCommand(wParam, lParam);
+
+ if (lr) return 0L;
+ }
+ break;
+
+ case WM_NOTIFY:
+ {
+ // Do Notification reflection if it came from a CWnd object
+ HWND hwndFrom = ((LPNMHDR)lParam)->hwndFrom;
+ CWnd* pWndFrom = GetApp()->GetCWndFromMap(hwndFrom);
+
+ if (pWndFrom != NULL)
+ lr = pWndFrom->OnNotifyReflect(wParam, lParam);
+ else
+ {
+ // Some controls (eg ListView) have child windows.
+ // Reflect those notifications too.
+ CWnd* pWndFromParent = GetApp()->GetCWndFromMap(::GetParent(hwndFrom));
+ if (pWndFromParent != NULL)
+ lr = pWndFromParent->OnNotifyReflect(wParam, lParam);
+ }
+
+ // Handle user notifications
+ if (!lr) lr = OnNotify(wParam, lParam);
+
+ // Set the return code for notifications
+ if (IsWindow())
+ SetWindowLongPtr(DWLP_MSGRESULT, (LONG_PTR)lr);
+
+ return (BOOL)lr;
+ }
+
+ case WM_PAINT:
+ {
+ if (::GetUpdateRect(m_hWnd, NULL, FALSE))
+ {
+ CPaintDC dc(this);
+ OnDraw(&dc);
+ }
+ else
+ // RedrawWindow can require repainting without an update rect
+ {
+ CClientDC dc(this);
+ OnDraw(&dc);
+ }
+
+ break;
+ }
+
+ case WM_ERASEBKGND:
+ {
+ CDC dc((HDC)wParam);
+ BOOL bResult = OnEraseBkgnd(&dc);
+ dc.Detach();
+ if (bResult) return TRUE;
+ }
+ break;
+
+ // A set of messages to be reflected back to the control that generated them
+ case WM_CTLCOLORBTN:
+ case WM_CTLCOLOREDIT:
+ case WM_CTLCOLORDLG:
+ case WM_CTLCOLORLISTBOX:
+ case WM_CTLCOLORSCROLLBAR:
+ case WM_CTLCOLORSTATIC:
+ case WM_DRAWITEM:
+ case WM_MEASUREITEM:
+ case WM_DELETEITEM:
+ case WM_COMPAREITEM:
+ case WM_CHARTOITEM:
+ case WM_VKEYTOITEM:
+ case WM_HSCROLL:
+ case WM_VSCROLL:
+ case WM_PARENTNOTIFY:
+ return MessageReflect(m_hWnd, uMsg, wParam, lParam);
+
+ } // switch(uMsg)
+ return FALSE;
+
+ } // INT_PTR CALLBACK CPropertyPage::DialogProc(...)
+
+ inline BOOL CPropertyPage::IsButtonEnabled(int iButton) const
+ {
+ assert(::IsWindow(m_hWnd));
+ return GetParent()->GetDlgItem(iButton)->IsWindowEnabled();
+ }
+
+ inline int CPropertyPage::OnApply()
+ {
+ // This function is called for each page when the Apply button is pressed
+ // Override this function in your derived class if required.
+
+ // The possible return values are:
+ // PSNRET_NOERROR. The changes made to this page are valid and have been applied
+ // PSNRET_INVALID. The property sheet will not be destroyed, and focus will be returned to this page.
+ // PSNRET_INVALID_NOCHANGEPAGE. The property sheet will not be destroyed, and focus will be returned;
+
+ return PSNRET_NOERROR;
+ }
+
+ inline void CPropertyPage::OnCancel()
+ {
+ // This function is called for each page when the Cancel button is pressed
+ // Override this function in your derived class if required.
+ }
+
+ inline void CPropertyPage::OnHelp()
+ {
+ // This function is called in response to the PSN_HELP notification.
+ SendMessage(m_hWnd, WM_COMMAND, ID_HELP, 0L);
+ }
+
+ inline BOOL CPropertyPage::OnQueryCancel()
+ {
+ // Called when the cancel button is pressed, and before the cancel has taken place
+ // Returns TRUE to prevent the cancel operation, or FALSE to allow it.
+
+ return FALSE; // Allow cancel to proceed
+ }
+
+ inline BOOL CPropertyPage::OnQuerySiblings(WPARAM wParam, LPARAM lParam)
+ {
+ UNREFERENCED_PARAMETER(wParam);
+ UNREFERENCED_PARAMETER(lParam);
+
+ // Responds to a query request from the Property Sheet.
+ // The values for wParam and lParam are the ones set by
+ // the CPropertySheet::QuerySiblings call
+
+ // return FALSE to allow other siblings to be queried, or
+ // return TRUE to stop query at this page.
+
+ return FALSE;
+ }
+
+ inline BOOL CPropertyPage::OnInitDialog()
+ {
+ // Called when the property page is created
+ // Override this function in your derived class if required.
+
+ return TRUE; // Pass Keyboard control to handle in WPARAM
+ }
+
+ inline BOOL CPropertyPage::OnKillActive()
+ {
+ // This is called in response to a PSN_KILLACTIVE notification, which
+ // is sent whenever the OK or Apply button is pressed.
+ // It provides an opportunity to validate the page contents before it's closed.
+ // Return TRUE to prevent the page from losing the activation, or FALSE to allow it.
+
+ return FALSE;
+ }
+
+ inline int CPropertyPage::OnOK()
+ {
+ // Called for each page when the OK button is pressed
+ // Override this function in your derived class if required.
+
+ // The possible return values are:
+ // PSNRET_NOERROR. The changes made to this page are valid and have been applied
+ // PSNRET_INVALID. The property sheet will not be destroyed, and focus will be returned to this page.
+ // PSNRET_INVALID_NOCHANGEPAGE. The property sheet will not be destroyed, and focus will be returned;
+
+ return PSNRET_NOERROR;
+ }
+
+ inline LRESULT CPropertyPage::OnNotify(WPARAM wParam, LPARAM lParam)
+ {
+ UNREFERENCED_PARAMETER(wParam);
+
+ LPPSHNOTIFY pNotify = (LPPSHNOTIFY)lParam;
+ switch(pNotify->hdr.code)
+ {
+ case PSN_SETACTIVE:
+ return OnSetActive();
+ case PSN_KILLACTIVE:
+ return OnKillActive();
+ case PSN_APPLY:
+ if (pNotify->lParam)
+ return OnOK();
+ else
+ return OnApply();
+ case PSN_RESET:
+ OnCancel();
+ return FALSE;
+ case PSN_QUERYCANCEL:
+ return OnQueryCancel();
+ case PSN_WIZNEXT:
+ return OnWizardNext();
+ case PSN_WIZBACK:
+ return OnWizardBack();
+ case PSN_WIZFINISH:
+ return OnWizardFinish();
+ case PSN_HELP:
+ OnHelp();
+ return TRUE;
+ }
+ return FALSE;
+ }
+
+ inline int CPropertyPage::OnSetActive()
+ {
+ // Called when a page becomes active
+ // Override this function in your derived class if required.
+
+ // Returns zero to accept the activation, or -1 to activate the next or the previous page (depending
+ // on whether the user clicked the Next or Back button). To set the activation to a particular page,
+ // return the resource identifier of the page.
+
+ return 0;
+ }
+
+ inline int CPropertyPage::OnWizardBack()
+ {
+ // This function is called when the Back button is pressed on a wizard page
+ // Override this function in your derived class if required.
+
+ // Returns 0 to allow the wizard to go to the previous page. Returns -1 to prevent the wizard
+ // from changing pages. To display a particular page, return its dialog resource identifier.
+
+ return 0;
+ }
+
+ inline INT_PTR CPropertyPage::OnWizardFinish()
+ {
+ // This function is called when the Finish button is pressed on a wizard page
+ // Override this function in your derived class if required.
+
+ // Return Value:
+ // Return non-zero to prevent the wizard from finishing.
+ // Version 5.80. and later. Return a window handle to prevent the wizard from finishing. The wizard will set the focus to that window. The window must be owned by the wizard page.
+ // Return 0 to allow the wizard to finish.
+
+ return 0; // Allow wizard to finish
+ }
+
+ inline int CPropertyPage::OnWizardNext()
+ {
+ // This function is called when the Next button is pressed on a wizard page
+ // Override this function in your derived class if required.
+
+ // Return 0 to allow the wizard to go to the next page. Return -1 to prevent the wizard from
+ // changing pages. To display a particular page, return its dialog resource identifier.
+
+ return 0;
+ }
+
+ inline BOOL CPropertyPage::PreTranslateMessage(MSG* pMsg)
+ {
+ // allow the tab control to translate keyboard input
+ if (pMsg->message == WM_KEYDOWN && GetAsyncKeyState(VK_CONTROL) < 0 &&
+ (pMsg->wParam == VK_TAB || pMsg->wParam == VK_PRIOR || pMsg->wParam == VK_NEXT))
+ {
+ CWnd* pWndParent = GetParent();
+ if (pWndParent->SendMessage(PSM_ISDIALOGMESSAGE, 0L, (LPARAM)pMsg))
+ return TRUE;
+ }
+
+ // allow the dialog to translate keyboard input
+ if ((pMsg->message >= WM_KEYFIRST) && (pMsg->message <= WM_KEYLAST))
+ {
+ if (IsDialogMessage(pMsg))
+ return TRUE;
+ }
+
+ return CWnd::PreTranslateMessage(pMsg);
+ }
+
+ inline LRESULT CPropertyPage::QuerySiblings(WPARAM wParam, LPARAM lParam) const
+ {
+ // Sent to a property sheet, which then forwards the message to each of its pages.
+ // Set wParam and lParam to values you want passed to the property pages.
+ // Returns the nonzero value from a page in the property sheet, or zero if no page returns a nonzero value.
+
+ assert(::IsWindow(m_hWnd));
+ return GetParent()->SendMessage(PSM_QUERYSIBLINGS, wParam, lParam);
+ }
+
+ inline void CPropertyPage::SetModified(BOOL bChanged) const
+ {
+ // The property sheet will enable the Apply button if bChanged is TRUE.
+
+ assert(::IsWindow(m_hWnd));
+
+ if (bChanged)
+ GetParent()->SendMessage(PSM_CHANGED, (WPARAM)m_hWnd, 0L);
+ else
+ GetParent()->SendMessage(PSM_UNCHANGED, (WPARAM)m_hWnd, 0L);
+ }
+
+ inline void CPropertyPage::SetTitle(LPCTSTR szTitle)
+ {
+ if (szTitle)
+ {
+ m_Title = szTitle;
+ m_PSP.dwFlags |= PSP_USETITLE;
+ }
+ else
+ {
+ m_Title.erase();
+ m_PSP.dwFlags &= ~PSP_USETITLE;
+ }
+
+ m_PSP.pszTitle = m_Title.c_str();
+ }
+
+ inline void CPropertyPage::SetWizardButtons(DWORD dwFlags) const
+ {
+ // dwFlags: A value that specifies which wizard buttons are enabled. You can combine one or more of the following flags.
+ // PSWIZB_BACK Enable the Back button. If this flag is not set, the Back button is displayed as disabled.
+ // PSWIZB_DISABLEDFINISH Display a disabled Finish button.
+ // PSWIZB_FINISH Display an enabled Finish button.
+ // PSWIZB_NEXT Enable the Next button. If this flag is not set, the Next button is displayed as disabled.
+
+ assert (::IsWindow(m_hWnd));
+ PropSheet_SetWizButtons(::GetParent(m_hWnd), dwFlags);
+ }
+
+ inline UINT CALLBACK CPropertyPage::StaticPropSheetPageProc(HWND hwnd, UINT uMsg, LPPROPSHEETPAGE ppsp)
+ {
+ assert( GetApp() );
+ UNREFERENCED_PARAMETER(hwnd);
+
+ // Note: the hwnd is always NULL
+
+ switch (uMsg)
+ {
+ case PSPCB_CREATE:
+ {
+ TLSData* pTLSData = (TLSData*)TlsGetValue(GetApp()->GetTlsIndex());
+ assert(pTLSData);
+
+ // Store the CPropertyPage pointer in Thread Local Storage
+ pTLSData->pCWnd = (CWnd*)ppsp->lParam;
+ }
+ break;
+ }
+
+ return TRUE;
+ }
+
+ inline INT_PTR CALLBACK CPropertyPage::StaticDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
+ {
+ assert( GetApp() );
+
+ // Find matching CWnd pointer for this HWND
+ CPropertyPage* pPage = (CPropertyPage*)GetApp()->GetCWndFromMap(hwndDlg);
+ if (0 == pPage)
+ {
+ // matching CWnd pointer not found, so add it to HWNDMap now
+ TLSData* pTLSData = (TLSData*)TlsGetValue(GetApp()->GetTlsIndex());
+ pPage = (CPropertyPage*)pTLSData->pCWnd;
+
+ // Set the hWnd members and call DialogProc for this message
+ pPage->m_hWnd = hwndDlg;
+ pPage->AddToMap();
+ }
+
+ return pPage->DialogProc(uMsg, wParam, lParam);
+ }
+
+
+ ///////////////////////////////////////////
+ // Definitions for the CPropertySheet class
+ //
+ inline CPropertySheet::CPropertySheet(UINT nIDCaption, CWnd* pParent /* = NULL*/)
+ {
+ ZeroMemory(&m_PSH, sizeof (PROPSHEETHEADER));
+ SetTitle(LoadString(nIDCaption));
+ m_bInitialUpdate = FALSE;
+
+#ifdef _WIN32_WCE
+ m_PSH.dwSize = sizeof(PROPSHEETHEADER);
+#else
+ if (GetComCtlVersion() >= 471)
+ m_PSH.dwSize = sizeof(PROPSHEETHEADER);
+ else
+ m_PSH.dwSize = PROPSHEETHEADER_V1_SIZE;
+#endif
+
+ m_PSH.dwFlags = PSH_PROPSHEETPAGE | PSH_USECALLBACK;
+ m_PSH.hwndParent = pParent? pParent->GetHwnd() : 0;
+ m_PSH.hInstance = GetApp()->GetInstanceHandle();
+ m_PSH.pfnCallback = (PFNPROPSHEETCALLBACK)CPropertySheet::Callback;
+ }
+
+ inline CPropertySheet::CPropertySheet(LPCTSTR pszCaption /*= NULL*/, CWnd* pParent /* = NULL*/)
+ {
+ ZeroMemory(&m_PSH, sizeof (PROPSHEETHEADER));
+ SetTitle(pszCaption);
+ m_bInitialUpdate = FALSE;
+
+#ifdef _WIN32_WCE
+ m_PSH.dwSize = PROPSHEETHEADER_V1_SIZE;
+#else
+ if (GetComCtlVersion() >= 471)
+ m_PSH.dwSize = sizeof(PROPSHEETHEADER);
+ else
+ m_PSH.dwSize = PROPSHEETHEADER_V1_SIZE;
+#endif
+
+ m_PSH.dwFlags = PSH_PROPSHEETPAGE | PSH_USECALLBACK;
+ m_PSH.hwndParent = pParent? pParent->GetHwnd() : 0;;
+ m_PSH.hInstance = GetApp()->GetInstanceHandle();
+ m_PSH.pfnCallback = (PFNPROPSHEETCALLBACK)CPropertySheet::Callback;
+ }
+
+ inline CPropertyPage* CPropertySheet::AddPage(CPropertyPage* pPage)
+ // Adds a Property Page to the Property Sheet
+ {
+ assert(NULL != pPage);
+
+ m_vPages.push_back(PropertyPagePtr(pPage));
+
+ if (m_hWnd)
+ {
+ // property sheet already exists, so add page to it
+ PROPSHEETPAGE psp = pPage->GetPSP();
+ HPROPSHEETPAGE hpsp = ::CreatePropertySheetPage(&psp);
+ PropSheet_AddPage(m_hWnd, hpsp);
+ }
+
+ m_PSH.nPages = (int)m_vPages.size();
+
+ return pPage;
+ }
+
+ inline void CPropertySheet::BuildPageArray()
+ // Builds the PROPSHEETPAGE array
+ {
+ m_vPSP.clear();
+ std::vector<PropertyPagePtr>::iterator iter;
+ for (iter = m_vPages.begin(); iter < m_vPages.end(); ++iter)
+ m_vPSP.push_back((*iter)->GetPSP());
+
+ PROPSHEETPAGE* pPSPArray = &m_vPSP.front(); // Array of PROPSHEETPAGE
+ m_PSH.ppsp = pPSPArray;
+ }
+
+ inline void CALLBACK CPropertySheet::Callback(HWND hwnd, UINT uMsg, LPARAM lParam)
+ {
+ assert( GetApp() );
+
+ switch(uMsg)
+ {
+ //called before the dialog is created, hwnd = NULL, lParam points to dialog resource
+ case PSCB_PRECREATE:
+ {
+ LPDLGTEMPLATE lpTemplate = (LPDLGTEMPLATE)lParam;
+
+ if(!(lpTemplate->style & WS_SYSMENU))
+ {
+ lpTemplate->style |= WS_SYSMENU;
+ }
+ }
+ break;
+
+ //called after the dialog is created
+ case PSCB_INITIALIZED:
+ {
+ // Retrieve pointer to CWnd object from Thread Local Storage
+ TLSData* pTLSData = (TLSData*)TlsGetValue(GetApp()->GetTlsIndex());
+ assert(pTLSData);
+
+ CPropertySheet* w = (CPropertySheet*)pTLSData->pCWnd;
+ assert(w);
+
+ w->Attach(hwnd);
+ w->OnCreate();
+ }
+ break;
+ }
+ }
+
+
+ inline HWND CPropertySheet::Create(CWnd* pParent /*= 0*/)
+ // Creates a modeless Property Sheet
+ {
+ assert( GetApp() );
+
+ if (pParent)
+ {
+ m_PSH.hwndParent = pParent->GetHwnd();
+ }
+
+ BuildPageArray();
+ PROPSHEETPAGE* pPSPArray = &m_vPSP.front();
+ m_PSH.ppsp = pPSPArray;
+
+ // Create a modeless Property Sheet
+ m_PSH.dwFlags &= ~PSH_WIZARD;
+ m_PSH.dwFlags |= PSH_MODELESS;
+ HWND hWnd = (HWND)CreatePropertySheet(&m_PSH);
+
+ return hWnd;
+ }
+
+ inline INT_PTR CPropertySheet::CreatePropertySheet(LPCPROPSHEETHEADER ppsph)
+ {
+ assert( GetApp() );
+
+ INT_PTR ipResult = 0;
+
+ // Only one window per CWnd instance allowed
+ assert(!::IsWindow(m_hWnd));
+
+ // Ensure this thread has the TLS index set
+ TLSData* pTLSData = GetApp()->SetTlsIndex();
+
+ // Store the 'this' pointer in Thread Local Storage
+ pTLSData->pCWnd = this;
+
+ // Create the property sheet
+ ipResult = PropertySheet(ppsph);
+
+ return ipResult;
+ }
+
+ inline void CPropertySheet::DestroyButton(int IDButton)
+ {
+ assert(::IsWindow(m_hWnd));
+
+ HWND hwndButton = ::GetDlgItem(m_hWnd, IDButton);
+ if (hwndButton != NULL)
+ {
+ // Hide and disable the button
+ ::ShowWindow(hwndButton, SW_HIDE);
+ ::EnableWindow(hwndButton, FALSE);
+ }
+ }
+
+ inline void CPropertySheet::Destroy()
+ {
+ CWnd::Destroy();
+ m_vPages.clear();
+ }
+
+ inline int CPropertySheet::DoModal()
+ {
+ assert( GetApp() );
+
+ BuildPageArray();
+ PROPSHEETPAGE* pPSPArray = &m_vPSP.front();
+ m_PSH.ppsp = pPSPArray;
+
+ // Create the Property Sheet
+ int nResult = (int)CreatePropertySheet(&m_PSH);
+
+ m_vPages.clear();
+
+ return nResult;
+ }
+
+ inline CPropertyPage* CPropertySheet::GetActivePage() const
+ {
+ assert(::IsWindow(m_hWnd));
+
+ CPropertyPage* pPage = NULL;
+ if (m_hWnd != NULL)
+ {
+ HWND hPage = (HWND)SendMessage(PSM_GETCURRENTPAGEHWND, 0L, 0L);
+ pPage = (CPropertyPage*)FromHandle(hPage);
+ }
+
+ return pPage;
+ }
+
+ inline int CPropertySheet::GetPageCount() const
+ // Returns the number of Property Pages in this Property Sheet
+ {
+ assert(::IsWindow(m_hWnd));
+ return (int)m_vPages.size();
+ }
+
+ inline int CPropertySheet::GetPageIndex(CPropertyPage* pPage) const
+ {
+ assert(::IsWindow(m_hWnd));
+
+ for (int i = 0; i < GetPageCount(); i++)
+ {
+ if (m_vPages[i].get() == pPage)
+ return i;
+ }
+ return -1;
+ }
+
+ inline HWND CPropertySheet::GetTabControl() const
+ // Returns the handle to the Property Sheet's tab control
+ {
+ assert(::IsWindow(m_hWnd));
+ return (HWND)SendMessage(PSM_GETTABCONTROL, 0L, 0L);
+ }
+
+ inline BOOL CPropertySheet::IsModeless() const
+ {
+ return (m_PSH.dwFlags & PSH_MODELESS);
+ }
+
+ inline BOOL CPropertySheet::IsWizard() const
+ {
+ return (m_PSH.dwFlags & PSH_WIZARD);
+ }
+
+ inline void CPropertySheet::RemovePage(CPropertyPage* pPage)
+ // Removes a Property Page from the Property Sheet
+ {
+ assert(::IsWindow(m_hWnd));
+
+ int nPage = GetPageIndex(pPage);
+ if (m_hWnd != NULL)
+ SendMessage(m_hWnd, PSM_REMOVEPAGE, nPage, 0L);
+
+ m_vPages.erase(m_vPages.begin() + nPage, m_vPages.begin() + nPage+1);
+ m_PSH.nPages = (int)m_vPages.size();
+ }
+
+ inline BOOL CPropertySheet::PreTranslateMessage(MSG* pMsg)
+ {
+ // allow sheet to translate Ctrl+Tab, Shift+Ctrl+Tab, Ctrl+PageUp, and Ctrl+PageDown
+ if (pMsg->message == WM_KEYDOWN && GetAsyncKeyState(VK_CONTROL) < 0 &&
+ (pMsg->wParam == VK_TAB || pMsg->wParam == VK_PRIOR || pMsg->wParam == VK_NEXT))
+ {
+ if (SendMessage(PSM_ISDIALOGMESSAGE, 0L, (LPARAM)pMsg))
+ return TRUE;
+ }
+
+ // allow the dialog to translate keyboard input
+ if ((pMsg->message >= WM_KEYFIRST) && (pMsg->message <= WM_KEYLAST))
+ {
+ return GetActivePage()->PreTranslateMessage(pMsg);
+ }
+
+ return CWnd::PreTranslateMessage(pMsg);
+ }
+
+ inline BOOL CPropertySheet::SetActivePage(int nPage)
+ {
+ assert(::IsWindow(m_hWnd));
+ return (BOOL)SendMessage(m_hWnd, PSM_SETCURSEL, nPage, 0L);
+ }
+
+ inline BOOL CPropertySheet::SetActivePage(CPropertyPage* pPage)
+ {
+ assert(::IsWindow(m_hWnd));
+ int nPage = GetPageIndex(pPage);
+ if ((nPage >= 0))
+ return SetActivePage(nPage);
+
+ return FALSE;
+ }
+
+ inline void CPropertySheet::SetIcon(UINT idIcon)
+ {
+ m_PSH.pszIcon = MAKEINTRESOURCE(idIcon);
+ m_PSH.dwFlags |= PSH_USEICONID;
+ }
+
+ inline void CPropertySheet::SetTitle(LPCTSTR szTitle)
+ {
+ if (szTitle)
+ m_Title = szTitle;
+ else
+ m_Title.erase();
+
+ m_PSH.pszCaption = m_Title.c_str();
+ }
+
+ inline void CPropertySheet::SetWizardMode(BOOL bWizard)
+ {
+ if (bWizard)
+ m_PSH.dwFlags |= PSH_WIZARD;
+ else
+ m_PSH.dwFlags &= ~PSH_WIZARD;
+ }
+
+ inline LRESULT CPropertySheet::WndProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam)
+ {
+ switch (uMsg)
+ {
+
+ case WM_WINDOWPOSCHANGED:
+ {
+ LPWINDOWPOS lpWinPos = (LPWINDOWPOS)lParam;
+ if (lpWinPos->flags & SWP_SHOWWINDOW)
+ {
+ if (!m_bInitialUpdate)
+ // The first window positioning with the window visible
+ OnInitialUpdate();
+ m_bInitialUpdate = TRUE;
+ }
+ }
+ break;
+
+ case WM_DESTROY:
+ m_bInitialUpdate = FALSE;
+ break;
+
+ case WM_SYSCOMMAND:
+ if ((SC_CLOSE == wParam) && (m_PSH.dwFlags & PSH_MODELESS))
+ {
+ Destroy();
+ return 0L;
+ }
+ break;
+ }
+
+ // pass unhandled messages on for default processing
+ return CWnd::WndProcDefault(uMsg, wParam, lParam);
+ }
+
+}
+
+#endif // _WIN32XX_PROPERTYSHEET_H_
diff --git a/mmc_updater/depends/win32cpp/rebar.h b/mmc_updater/depends/win32cpp/rebar.h
new file mode 100644
index 00000000..1a339dca
--- /dev/null
+++ b/mmc_updater/depends/win32cpp/rebar.h
@@ -0,0 +1,709 @@
+// Win32++ Version 7.2
+// Released: 5th AUgust 2011
+//
+// David Nash
+// email: dnash@bigpond.net.au
+// url: https://sourceforge.net/projects/win32-framework
+//
+//
+// Copyright (c) 2005-2011 David Nash
+//
+// Permission is hereby granted, free of charge, to
+// any person obtaining a copy of this software and
+// associated documentation files (the "Software"),
+// to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify,
+// merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom
+// the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice
+// shall be included in all copies or substantial portions
+// of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
+// OR OTHER DEALINGS IN THE SOFTWARE.
+//
+////////////////////////////////////////////////////////
+
+
+#ifndef _WIN32XX_REBAR_H_
+#define _WIN32XX_REBAR_H_
+
+#include "wincore.h"
+#include "gdi.h"
+
+
+namespace Win32xx
+{
+
+ struct ReBarTheme
+ {
+ BOOL UseThemes; // TRUE if themes are used
+ COLORREF clrBkgnd1; // Colour 1 for rebar background
+ COLORREF clrBkgnd2; // Colour 2 for rebar background
+ COLORREF clrBand1; // Colour 1 for rebar band background. Use NULL if not required
+ COLORREF clrBand2; // Colour 2 for rebar band background. Use NULL if not required
+ BOOL FlatStyle; // Bands are rendered with flat rather than raised style
+ BOOL BandsLeft; // Position bands left on rearrange
+ BOOL LockMenuBand; // Lock MenuBar's band in dedicated top row, without gripper
+ BOOL RoundBorders; // Use rounded band borders
+ BOOL ShortBands; // Allows bands to be shorter than maximum available width
+ BOOL UseLines; // Displays horizontal lines between bands
+ };
+
+ ////////////////////////////////////
+ // Declaration of the CReBar class
+ //
+ class CReBar : public CWnd
+ {
+ public:
+ CReBar();
+ virtual ~CReBar();
+
+ // Operations
+ BOOL DeleteBand(const int nBand) const;
+ int HitTest(RBHITTESTINFO& rbht);
+ HWND HitTest(POINT pt);
+ int IDToIndex(UINT uBandID) const;
+ BOOL InsertBand(const int nBand, REBARBANDINFO& rbbi) const;
+ BOOL IsBandVisible(int nBand) const;
+ void MaximizeBand(UINT uBand, BOOL fIdeal = FALSE);
+ void MinimizeBand(UINT uBand);
+ BOOL MoveBand(UINT uFrom, UINT uTo);
+ void MoveBandsLeft();
+ BOOL ResizeBand(const int nBand, const CSize& sz) const;
+ BOOL ShowGripper(int nBand, BOOL fShow) const;
+ BOOL ShowBand(int nBand, BOOL fShow) const;
+ BOOL SizeToRect(CRect& rect) const;
+
+ // Attributes
+ int GetBand(const HWND hWnd) const;
+ CRect GetBandBorders(int nBand) const;
+ int GetBandCount() const;
+ BOOL GetBandInfo(const int nBand, REBARBANDINFO& rbbi) const;
+ CRect GetBandRect(int i) const;
+ UINT GetBarHeight() const;
+ BOOL GetBarInfo(REBARINFO& rbi) const;
+ HWND GetMenuBar() {return m_hMenuBar;}
+ ReBarTheme& GetReBarTheme() {return m_Theme;}
+ UINT GetRowCount() const;
+ int GetRowHeight(int nRow) const;
+ UINT GetSizeofRBBI() const;
+ HWND GetToolTips() const;
+ BOOL SetBandBitmap(const int nBand, const CBitmap* pBackground) const;
+ BOOL SetBandColor(const int nBand, const COLORREF clrFore, const COLORREF clrBack) const;
+ BOOL SetBandInfo(const int nBand, REBARBANDINFO& rbbi) const;
+ BOOL SetBarInfo(REBARINFO& rbi) const;
+ void SetMenuBar(HWND hMenuBar) {m_hMenuBar = hMenuBar;}
+ void SetReBarTheme(ReBarTheme& Theme);
+
+ protected:
+ //Overridables
+ virtual BOOL OnEraseBkgnd(CDC* pDC);
+ virtual void PreCreate(CREATESTRUCT& cs);
+ virtual void PreRegisterClass(WNDCLASS &wc);
+ virtual LRESULT WndProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam);
+
+ private:
+ CReBar(const CReBar&); // Disable copy construction
+ CReBar& operator = (const CReBar&); // Disable assignment operator
+
+ ReBarTheme m_Theme;
+ BOOL m_bIsDragging;
+ HWND m_hMenuBar;
+ LPARAM m_Orig_lParam;
+ };
+
+}
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+namespace Win32xx
+{
+
+ ///////////////////////////////////
+ // Definitions for the CReBar class
+ //
+ inline CReBar::CReBar() : m_bIsDragging(FALSE), m_hMenuBar(0), m_Orig_lParam(0L)
+ {
+ ZeroMemory(&m_Theme, sizeof(ReBarTheme));
+ }
+
+ inline CReBar::~CReBar()
+ {
+ }
+
+ inline BOOL CReBar::DeleteBand(int nBand) const
+ // Deletes a band from a rebar control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (BOOL)SendMessage(RB_DELETEBAND, nBand, 0L);
+ }
+
+ inline int CReBar::GetBand(HWND hWnd) const
+ // Returns the zero based band number for this window handle
+ {
+ assert(::IsWindow(m_hWnd));
+
+ int nResult = -1;
+ if (NULL == hWnd) return nResult;
+
+ for (int nBand = 0; nBand < GetBandCount(); ++nBand)
+ {
+ REBARBANDINFO rbbi = {0};
+ rbbi.cbSize = GetSizeofRBBI();
+ rbbi.fMask = RBBIM_CHILD;
+ GetBandInfo(nBand, rbbi);
+ if (rbbi.hwndChild == hWnd)
+ nResult = nBand;
+ }
+
+ return nResult;
+ }
+
+ inline CRect CReBar::GetBandBorders(int nBand) const
+ // Retrieves the borders of a band.
+ {
+ assert(::IsWindow(m_hWnd));
+
+ CRect rc;
+ SendMessage(RB_GETBANDBORDERS, nBand, (LPARAM)&rc);
+ return rc;
+ }
+
+ inline int CReBar::GetBandCount() const
+ // Retrieves the count of bands currently in the rebar control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (int)SendMessage(RB_GETBANDCOUNT, 0L, 0L);
+ }
+
+ inline BOOL CReBar::GetBandInfo(int nBand, REBARBANDINFO& rbbi) const
+ // Retrieves information about a specified band in a rebar control.
+ {
+ assert(::IsWindow(m_hWnd));
+ assert(nBand >= 0);
+
+ // REBARBANDINFO describes individual BAND characteristics
+ rbbi.cbSize = GetSizeofRBBI();
+ return (BOOL)SendMessage(RB_GETBANDINFO, nBand, (LPARAM)&rbbi);
+ }
+
+ inline CRect CReBar::GetBandRect(int i) const
+ // Retrieves the bounding rectangle for a given band in a rebar control.
+ {
+ assert(::IsWindow(m_hWnd));
+ CRect rc;
+ SendMessage(RB_GETRECT, i, (LPARAM)&rc);
+ return rc;
+ }
+
+ inline UINT CReBar::GetBarHeight() const
+ // Retrieves the height of the rebar control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (UINT)SendMessage(RB_GETBARHEIGHT, 0L, 0L);
+ }
+
+ inline BOOL CReBar::GetBarInfo(REBARINFO& rbi) const
+ // Retrieves information about the rebar control and the image list it uses.
+ {
+ assert(::IsWindow(m_hWnd));
+
+ // REBARINFO describes overall rebar control characteristics
+ rbi.cbSize = GetSizeofRBBI();
+ return (BOOL)SendMessage(RB_GETBARINFO, 0L, (LPARAM)&rbi);
+ }
+
+ inline UINT CReBar::GetRowCount() const
+ // Retrieves the number of rows of bands in a rebar control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (UINT)SendMessage(RB_GETROWCOUNT, 0L, 0L);
+ }
+
+ inline int CReBar::GetRowHeight(int nRow) const
+ // Retrieves the height of a specified row in a rebar control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (int)SendMessage(RB_GETROWHEIGHT, nRow, 0L);
+ }
+
+ inline UINT CReBar::GetSizeofRBBI() const
+ // The size of the REBARBANDINFO struct changes according to _WIN32_WINNT
+ // sizeof(REBARBANDINFO) can report an incorrect size for older Window versions,
+ // or newer Window version without XP themes enabled.
+ // Use this function to get a safe size for REBARBANDINFO.
+ {
+ assert(::IsWindow(m_hWnd));
+
+ UINT uSizeof = sizeof(REBARBANDINFO);
+
+ #if defined REBARBANDINFO_V6_SIZE // only defined for VS2008 or higher
+ #if !defined (_WIN32_WINNT) || _WIN32_WINNT >= 0x0600
+ if ((GetWinVersion() < 2600) || (GetComCtlVersion() < 610)) // Vista and Vista themes?
+ uSizeof = REBARBANDINFO_V6_SIZE;
+ #endif
+ #endif
+
+ return uSizeof;
+ }
+
+ inline HWND CReBar::GetToolTips() const
+ // Retrieves the handle to any ToolTip control associated with the rebar control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (HWND)SendMessage(RB_GETTOOLTIPS, 0L, 0L);
+ }
+
+ inline int CReBar::HitTest(RBHITTESTINFO& rbht)
+ // Determines which portion of a rebar band is at a given point on the screen,
+ // if a rebar band exists at that point.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (int)SendMessage(RB_HITTEST, 0L, (LPARAM)&rbht);
+ }
+
+ inline HWND CReBar::HitTest(POINT pt)
+ // Return the child HWND at the given point
+ {
+ assert(::IsWindow(m_hWnd));
+
+ // Convert the point to client co-ordinates
+ ScreenToClient(pt);
+
+ // Get the rebar band with the point
+ RBHITTESTINFO rbhti = {0};
+ rbhti.pt = pt;
+ int iBand = HitTest(rbhti);
+
+ if (iBand >= 0)
+ {
+ // Get the rebar band's hWnd
+ REBARBANDINFO rbbi = {0};
+ rbbi.cbSize = GetSizeofRBBI();
+ rbbi.fMask = RBBIM_CHILD;
+ GetBandInfo(iBand, rbbi);
+
+ return rbbi.hwndChild;
+ }
+ else
+ return NULL;
+ }
+
+ inline int CReBar::IDToIndex(UINT uBandID) const
+ // Converts a band identifier to a band index in a rebar control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (int)SendMessage(RB_IDTOINDEX, (WPARAM)uBandID, 0L);
+ }
+
+ inline BOOL CReBar::InsertBand(int nBand, REBARBANDINFO& rbbi) const
+ // Inserts a new band in a rebar control.
+ {
+ assert(::IsWindow(m_hWnd));
+
+ rbbi.cbSize = GetSizeofRBBI();
+ return (BOOL)SendMessage(RB_INSERTBAND, nBand, (LPARAM)&rbbi);
+ }
+
+ inline BOOL CReBar::IsBandVisible(int nBand) const
+ // Returns true if the band is visible
+ {
+ assert(::IsWindow(m_hWnd));
+
+ REBARBANDINFO rbbi = {0};
+ rbbi.cbSize = GetSizeofRBBI();
+ rbbi.fMask = RBBIM_STYLE;
+ GetBandInfo(nBand, rbbi);
+
+ return !(rbbi.fStyle & RBBS_HIDDEN);
+ }
+
+ inline BOOL CReBar::OnEraseBkgnd(CDC* pDC)
+ {
+ BOOL Erase = TRUE;
+ if (!m_Theme.UseThemes)
+ Erase = FALSE;
+
+ if (!m_Theme.clrBkgnd1 && !m_Theme.clrBkgnd2 && !m_Theme.clrBand1 && !m_Theme.clrBand2)
+ Erase = FALSE;
+
+ if (Erase)
+ {
+ CRect rcReBar = GetClientRect();
+ int BarWidth = rcReBar.Width();
+ int BarHeight = rcReBar.Height();
+
+ // Create and set up our memory DC
+ CMemDC MemDC(pDC);
+ MemDC.CreateCompatibleBitmap(pDC, BarWidth, BarHeight);
+
+ // Draw to ReBar background to the memory DC
+ rcReBar.right = 600;
+ MemDC.GradientFill(m_Theme.clrBkgnd1, m_Theme.clrBkgnd2, rcReBar, TRUE);
+ if (BarWidth >= 600)
+ {
+ rcReBar.left = 600;
+ rcReBar.right = BarWidth;
+ MemDC.SolidFill(m_Theme.clrBkgnd2, rcReBar);
+ }
+
+ if (m_Theme.clrBand1 || m_Theme.clrBand2)
+ {
+ // Draw the individual band backgrounds
+ for (int nBand = 0 ; nBand < GetBandCount(); ++nBand)
+ {
+ if (IsBandVisible(nBand))
+ {
+ if (nBand != GetBand(m_hMenuBar))
+ {
+ // Determine the size of this band
+ CRect rcBand = GetBandRect(nBand);
+
+ // Determine the size of the child window
+ REBARBANDINFO rbbi = {0};
+ rbbi.cbSize = GetSizeofRBBI();
+ rbbi.fMask = RBBIM_CHILD ;
+ GetBandInfo(nBand, rbbi);
+ CRect rcChild;
+ ::GetWindowRect(rbbi.hwndChild, &rcChild);
+ int ChildWidth = rcChild.right - rcChild.left;
+
+ // Determine our drawing rectangle
+ CRect rcDraw = rcBand;
+ rcDraw.bottom = rcDraw.top + (rcBand.bottom - rcBand.top)/2;
+ int xPad = IsXPThemed()? 2: 0;
+ rcDraw.left -= xPad;
+
+ // Fill the Source CDC with the band's background
+ CMemDC SourceDC(pDC);
+ SourceDC.CreateCompatibleBitmap(pDC, BarWidth, BarHeight);
+ CRect rcBorder = GetBandBorders(nBand);
+ rcDraw.right = rcBand.left + ChildWidth + rcBorder.left;
+ SourceDC.SolidFill(m_Theme.clrBand1, rcDraw);
+ rcDraw.top = rcDraw.bottom;
+ rcDraw.bottom = rcBand.bottom;
+ SourceDC.GradientFill(m_Theme.clrBand1, m_Theme.clrBand2, rcDraw, FALSE);
+
+ // Set Curve amount for rounded edges
+ int Curve = m_Theme.RoundBorders? 12 : 0;
+
+ // Create our mask for rounded edges using RoundRect
+ CMemDC MaskDC(pDC);
+ MaskDC.CreateCompatibleBitmap(pDC, BarWidth, BarHeight);
+
+ rcDraw.top = rcBand.top;
+ if (!m_Theme.FlatStyle)
+ ::InflateRect(&rcDraw, 1, 1);
+
+ int left = rcDraw.left;
+ int right = rcDraw.right;
+ int top = rcDraw.top;
+ int bottom = rcDraw.bottom;
+ int cx = rcDraw.right - rcBand.left + xPad;
+ int cy = rcDraw.bottom - rcBand.top;
+
+ if (m_Theme.FlatStyle)
+ {
+ MaskDC.SolidFill(RGB(0,0,0), rcDraw);
+ MaskDC.BitBlt(left, top, cx, cy, &MaskDC, left, top, PATINVERT);
+ MaskDC.RoundRect(left, top, right, bottom, Curve, Curve);
+ }
+ else
+ {
+ MaskDC.SolidFill(RGB(0,0,0), rcDraw);
+ MaskDC.RoundRect(left, top, right, bottom, Curve, Curve);
+ MaskDC.BitBlt(left, top, cx, cy, &MaskDC, left, top, PATINVERT);
+ }
+
+ // Copy Source DC to Memory DC using the RoundRect mask
+ MemDC.BitBlt(left, top, cx, cy, &SourceDC, left, top, SRCINVERT);
+ MemDC.BitBlt(left, top, cx, cy, &MaskDC, left, top, SRCAND);
+ MemDC.BitBlt(left, top, cx, cy, &SourceDC, left, top, SRCINVERT);
+
+ // Extra drawing to prevent jagged edge while moving bands
+ if (m_bIsDragging)
+ {
+ CClientDC ReBarDC(this);
+ ReBarDC.BitBlt(rcDraw.right - ChildWidth, rcDraw.top, ChildWidth, cy, &MemDC, rcDraw.right - ChildWidth, rcDraw.top, SRCCOPY);
+ }
+ }
+ }
+ }
+ }
+
+ if (m_Theme.UseLines)
+ {
+ // Draw lines between bands
+ for (int j = 0; j < GetBandCount()-1; ++j)
+ {
+ rcReBar = GetBandRect(j);
+ rcReBar.left = MAX(0, rcReBar.left - 4);
+ rcReBar.bottom +=2;
+ MemDC.DrawEdge(rcReBar, EDGE_ETCHED, BF_BOTTOM | BF_ADJUST);
+ }
+ }
+
+ // Copy the Memory DC to the window's DC
+ pDC->BitBlt(0, 0, BarWidth, BarHeight, &MemDC, 0, 0, SRCCOPY);
+ }
+
+ return Erase;
+ }
+
+ inline void CReBar::PreCreate(CREATESTRUCT &cs)
+ // Sets the CREATESTRUCT paramaters prior to window creation
+ {
+ cs.style = WS_VISIBLE | WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS |
+ CCS_NODIVIDER | RBS_VARHEIGHT | RBS_BANDBORDERS ;
+
+ cs.cy = 100;
+ }
+
+ inline void CReBar::PreRegisterClass(WNDCLASS &wc)
+ {
+ // Set the Window Class
+ wc.lpszClassName = REBARCLASSNAME;
+ }
+
+ inline void CReBar::MaximizeBand(UINT uBand, BOOL fIdeal /*= FALSE*/)
+ // Resizes a band in a rebar control to either its ideal or largest size.
+ {
+ assert(::IsWindow(m_hWnd));
+ SendMessage(RB_MAXIMIZEBAND, (WPARAM)uBand, (LPARAM)fIdeal);
+ }
+
+ inline void CReBar::MinimizeBand(UINT uBand)
+ // Resizes a band in a rebar control to its smallest size.
+ {
+ assert(::IsWindow(m_hWnd));
+ SendMessage(RB_MINIMIZEBAND, (WPARAM)uBand, 0L);
+ }
+
+ inline BOOL CReBar::MoveBand(UINT uFrom, UINT uTo)
+ // Moves a band from one index to another.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (BOOL)SendMessage(RB_MOVEBAND, (WPARAM)uFrom, (LPARAM)uTo);
+ }
+
+ inline void CReBar::MoveBandsLeft()
+ // Repositions the bands so they are left justified
+ {
+ assert(::IsWindow(m_hWnd));
+
+ int OldrcTop = -1;
+ for (int nBand = GetBandCount() -1; nBand >= 0; --nBand)
+ {
+ CRect rc = GetBandRect(nBand);
+ if (rc.top != OldrcTop)
+ {
+ // Maximize the last band on each row
+ if (IsBandVisible(nBand))
+ {
+ ::SendMessage(GetHwnd(), RB_MAXIMIZEBAND, nBand, 0L);
+ OldrcTop = rc.top;
+ }
+ }
+ }
+ }
+
+ inline BOOL CReBar::ResizeBand(int nBand, const CSize& sz) const
+ // Sets a band's size
+ {
+ assert(::IsWindow(m_hWnd));
+
+ REBARBANDINFO rbbi = {0};
+ rbbi.cbSize = GetSizeofRBBI();
+ rbbi.fMask = RBBIM_CHILDSIZE | RBBIM_SIZE;
+
+ GetBandInfo(nBand, rbbi);
+ rbbi.cx = sz.cx + 2;
+ rbbi.cxMinChild = sz.cx + 2;
+ rbbi.cyMinChild = sz.cy;
+ rbbi.cyMaxChild = sz.cy;
+
+ return SetBandInfo(nBand, rbbi );
+ }
+
+ inline BOOL CReBar::SetBandBitmap(int nBand, const CBitmap* pBackground) const
+ // Sets the band's bitmaps
+ {
+ assert(::IsWindow(m_hWnd));
+ assert(pBackground);
+
+ REBARBANDINFO rbbi = {0};
+ rbbi.cbSize = GetSizeofRBBI();
+ rbbi.fMask = RBBIM_STYLE;
+ GetBandInfo(nBand, rbbi);
+ rbbi.fMask |= RBBIM_BACKGROUND;
+ rbbi.hbmBack = *pBackground;
+
+ return (BOOL)SendMessage(RB_SETBANDINFO, nBand, (LPARAM)&rbbi);
+ }
+
+ inline BOOL CReBar::SetBandColor(int nBand, COLORREF clrFore, COLORREF clrBack) const
+ // Sets the band's color
+ // Note: No effect with XP themes enabled
+ // No effect if a bitmap has been set
+ {
+ assert(::IsWindow(m_hWnd));
+
+ REBARBANDINFO rbbi = {0};
+ rbbi.cbSize = GetSizeofRBBI();
+ rbbi.fMask = RBBIM_COLORS;
+ rbbi.clrFore = clrFore;
+ rbbi.clrBack = clrBack;
+
+ return (BOOL)SendMessage(RB_SETBANDINFO, nBand, (LPARAM)&rbbi);
+ }
+
+ inline BOOL CReBar::SetBandInfo(int nBand, REBARBANDINFO& rbbi) const
+ // Sets the characteristics of a rebar control.
+ {
+ assert(::IsWindow(m_hWnd));
+ assert(nBand >= 0);
+
+ // REBARBANDINFO describes individual BAND characteristics0
+ rbbi.cbSize = GetSizeofRBBI();
+ return (BOOL)SendMessage(RB_SETBANDINFO, nBand, (LPARAM)&rbbi);
+ }
+
+ inline BOOL CReBar::SetBarInfo(REBARINFO& rbi) const
+ // REBARINFO associates an image list with the rebar
+ // A band will also need to set RBBIM_IMAGE
+ {
+ assert(::IsWindow(m_hWnd));
+
+ rbi.cbSize = GetSizeofRBBI();
+ return (BOOL)SendMessage(RB_SETBARINFO, 0L, (LPARAM)&rbi);
+ }
+
+ inline void CReBar::SetReBarTheme(ReBarTheme& Theme)
+ {
+ m_Theme.UseThemes = Theme.UseThemes;
+ m_Theme.clrBkgnd1 = Theme.clrBkgnd1;
+ m_Theme.clrBkgnd2 = Theme.clrBkgnd2;
+ m_Theme.clrBand1 = Theme.clrBand1;
+ m_Theme.clrBand2 = Theme.clrBand2;
+ m_Theme.BandsLeft = Theme.BandsLeft;
+ m_Theme.LockMenuBand = Theme.LockMenuBand;
+ m_Theme.ShortBands = Theme.ShortBands;
+ m_Theme.UseLines = Theme.UseLines;
+ m_Theme.FlatStyle = Theme.FlatStyle;
+ m_Theme.RoundBorders = Theme.RoundBorders;
+
+ if (IsWindow())
+ {
+ if (m_Theme.LockMenuBand)
+ ShowGripper(GetBand(m_hMenuBar), FALSE);
+ else
+ ShowGripper(GetBand(m_hMenuBar), TRUE);
+
+ Invalidate();
+ }
+ }
+
+ inline BOOL CReBar::ShowBand(int nBand, BOOL fShow) const
+ // Show or hide a band
+ {
+ assert(::IsWindow(m_hWnd));
+ return (BOOL)SendMessage(RB_SHOWBAND, (WPARAM)nBand, (LPARAM)fShow);
+ }
+
+ inline BOOL CReBar::ShowGripper(int nBand, BOOL fShow) const
+ // Show or hide the band's gripper
+ {
+ assert(::IsWindow(m_hWnd));
+
+ REBARBANDINFO rbbi = {0};
+ rbbi.cbSize = GetSizeofRBBI();
+ rbbi.fMask = RBBIM_STYLE;
+ GetBandInfo(nBand, rbbi);
+ if (fShow)
+ {
+ rbbi.fStyle |= RBBS_GRIPPERALWAYS;
+ rbbi.fStyle &= ~RBBS_NOGRIPPER;
+ }
+ else
+ {
+ rbbi.fStyle &= ~RBBS_GRIPPERALWAYS;
+ rbbi.fStyle |= RBBS_NOGRIPPER;
+ }
+
+ return SetBandInfo(nBand, rbbi);
+ }
+
+ inline BOOL CReBar::SizeToRect(CRect& rect) const
+ // Attempts to find the best layout of the bands for the given rectangle.
+ // The rebar bands will be arranged and wrapped as necessary to fit the rectangle.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (BOOL)SendMessage(RB_SIZETORECT, 0, (LPARAM) (LPRECT)rect);
+ }
+
+ inline LRESULT CReBar::WndProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam)
+ {
+ switch (uMsg)
+ {
+ case WM_MOUSEMOVE:
+ if (m_Theme.UseThemes && m_Theme.LockMenuBand)
+ {
+ // We want to lock the first row in place, but allow other bands to move!
+ // Use move messages to limit the resizing of bands
+ int y = GET_Y_LPARAM(lParam);
+
+ if (y <= GetRowHeight(0))
+ return 0L; // throw this message away
+ }
+ break;
+ case WM_LBUTTONDOWN:
+ m_Orig_lParam = lParam; // Store the x,y position
+ m_bIsDragging = TRUE;
+ break;
+ case WM_LBUTTONUP:
+ if (m_Theme.UseThemes && m_Theme.LockMenuBand)
+ {
+ // Use move messages to limit the resizing of bands
+ int y = GET_Y_LPARAM(lParam);
+
+ if (y <= GetRowHeight(0))
+ {
+ // Use x,y from WM_LBUTTONDOWN for WM_LBUTTONUP position
+ lParam = m_Orig_lParam;
+ }
+ }
+ m_bIsDragging = FALSE;
+ break;
+ case UWM_GETREBARTHEME:
+ {
+ ReBarTheme& rm = GetReBarTheme();
+ return (LRESULT)&rm;
+ }
+ case UWM_TOOLBAR_RESIZE:
+ {
+ HWND hToolBar = (HWND)wParam;
+ LPSIZE pToolBarSize = (LPSIZE)lParam;
+ ResizeBand(GetBand(hToolBar), *pToolBarSize);
+ }
+ break;
+ }
+
+ // pass unhandled messages on for default processing
+ return CWnd::WndProcDefault(uMsg, wParam, lParam);
+ }
+
+} // namespace Win32xx
+
+#endif // #ifndef _WIN32XX_REBAR_H_
diff --git a/mmc_updater/depends/win32cpp/release notes.txt b/mmc_updater/depends/win32cpp/release notes.txt
new file mode 100644
index 00000000..bc3114da
--- /dev/null
+++ b/mmc_updater/depends/win32cpp/release notes.txt
@@ -0,0 +1,116 @@
+About Win32++
+-------------
+Win32++ is simple and easy to understand framework for developing Win32
+applications using C++. It brings an object oriented approach to programming
+directly with the Win32 API. Each window created is a C++ class object capable
+of having its own window procedure for routing messages.
+
+Win32++ supports the following compilers and development environments:
+* Borland C++ Compiler 5.5
+* Borland Developer Studio 2006
+* Dev-C++
+* Microsoft Visual C++ Toolkit 2003
+* Microsoft Visual C++ 2005 Express Edition
+* Microsoft Visual C++ 2008 Express Edition
+* Microsoft Visual C++ 2010 Express Edition
+* Microsoft Visual Studio 6.0
+* Microsoft Visual Studio.net 2003
+* Microsoft Visual Studio.net 2005
+* Microsoft Visual Studio.net 2008
+* Microsoft Visual Studio.net 2010
+* MinGW compiler
+
+Win32++ supports the following operating systems
+* Windows 95
+* Windows 98
+* Windows ME
+* Windows NT 4
+* Windows 2000
+* Windows XP (32bit and 64bit)
+* Windows 2003 Server (32bit and 64bit)
+* Windows Vista (32bit and 64bit)
+* Windows 2008 Server (32bit and 64bit)
+* Windows 7 (32 bit and 64 bit)
+* Windows CE from WCE400 (Windows mobile 2003) to WCE600 (Windows mobile 6)
+
+
+Features
+--------
+Win32++ code has the following features
+ * Object Orientated
+ * Subclassing support
+ * Notification reflection and message reflection
+ * Unicode compliant, with multilingual support
+ * Multi-threaded support.
+ * Tracing
+ * 64 bit support
+ * Windows 7 ribbon support
+ * Themes support
+ * Network support (including IP version 6)
+ * Docking windows
+ * Tabbed MDIs
+
+Frames produced by Win32++ include the following:
+ * Rebar
+ * Menubar
+ * Toolbar
+ * Status bar
+ * Tool tips
+
+About the file downloads
+------------------------
+The file download from Sourceforge includes the following:
+ * The Win32++ library itself
+ * Help for the library
+ * A set of tutorials
+ * A collection of sample applications
+
+The sample applications include:
+ * Browser - An Internet browser application with an event sink.
+ * Dialog - An example of a simple dialog application.
+ * DialogDemo - An interative dialog application demonstrating slider controls and progress bars.
+ * DialogResizing - An example of a resizable dialog.
+ * DialogTab - A dialog application with a tab control.
+ * DirectX - A simple DirectX application.
+ * DLL - Shows how to run Win32++ from within a DLL
+ * Dock - An example of a simple docking application.
+ * DockContainer - An example of a docking application which incorporates containers.
+ * DockTabbedMDI - An example of a docking application with containers and a tabbed MDI.
+ * Explorer - A Windows Explorer-like application.
+ * FastGDI - An application which demonstrates direct manipulation of a bitmap's colour.
+ * FormDemo - An example of a modeless dialog within a frame.
+ * Frame - A simple frame application.
+ * GDIPlus - Demonstrates how to use GDI+ with Win32++.
+ * MDIFrame - A simple MDI frame application.
+ * MDIFrameDemo - Demonstrates some additional features of MDI frames.
+ * MDIFrameSplitter - Demonstrates how to implement splitter windows in MDI Child windows.
+ * Networking - Demonstrates the use of networking.
+ * Notepad - A simple text editor with printing.
+ * Performance - Measures Win32++'s message handling speed.
+ * Picture - A simple picture rendering application.
+ * PropertySheets - A demonstration of property sheets.
+ * RibbonFrame - Demonstrates how to use the Windows 7 ribbon with a frame.
+ * RibbonSimple - Demonstrates how to use the Windwos 7 ribbon with a simple window.
+ * Scribble - A simple drawing application.
+ * Simple - Creates a simple window.
+ * Splitter - Demonstrates how to use dockers to create splitter windows.
+ * TabDemo - Demonstrates the use of a CTab control in a frame.
+ * TaskDialog - Demonstrates the use of task dialogs (available on Vista and above).
+ * Themes - Demonstrates how to customise the colours for rebar and toolbar controls.
+ * Threads - Demonstrates multi-threaded Windows.
+ * Tray - Demonstrates how to "minimise" an application to the system tray.
+ * WinCE samples - A small collection of samples for Windows CE
+
+Getting Started
+---------------
+Each file download includes the project files for Dev-C++, CodeBlocks and the
+various compilers from Microsoft. CodeBlocks is an IDE (Integrated Development
+Environment) that supports GNU GCC, Borland Developer Studio 2006 and Microsoft
+C++ Toolkit 2003.
+
+You can start with one of the sample programs, and add your code. Alternatively
+you can start with the projects and sample code provided in the "new projects"
+folder.
+
+For additional information on getting started, refer to the help included
+in the documentation. \ No newline at end of file
diff --git a/mmc_updater/depends/win32cpp/ribbon.h b/mmc_updater/depends/win32cpp/ribbon.h
new file mode 100644
index 00000000..9f6dac5c
--- /dev/null
+++ b/mmc_updater/depends/win32cpp/ribbon.h
@@ -0,0 +1,527 @@
+// Win32++ Version 7.2
+// Released: 5th AUgust 2011
+//
+// David Nash
+// email: dnash@bigpond.net.au
+// url: https://sourceforge.net/projects/win32-framework
+//
+//
+// Copyright (c) 2005-2011 David Nash
+//
+// Permission is hereby granted, free of charge, to
+// any person obtaining a copy of this software and
+// associated documentation files (the "Software"),
+// to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify,
+// merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom
+// the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice
+// shall be included in all copies or substantial portions
+// of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
+// OR OTHER DEALINGS IN THE SOFTWARE.
+//
+////////////////////////////////////////////////////////
+
+
+///////////////////////////////////////////////////////
+// ribbon.h
+// Declaration of the following classes:
+// CRibbon and CRibbonFrame
+//
+
+#ifndef _WIN32XX_RIBBON_H_
+#define _WIN32XX_RIBBON_H_
+
+
+// Notes: 1) The Windows 7 SDK must be installed and its directories added to the IDE
+// 2) The ribbon only works on OS Windows 7 and above
+
+//#include <strsafe.h>
+#include <UIRibbon.h> // Contained within the Windows 7 SDK
+#include <UIRibbonPropertyHelpers.h>
+
+namespace Win32xx
+{
+ // Defines the callback entry-point methods for the Ribbon framework.
+ class CRibbon : public IUICommandHandler, public IUIApplication
+ {
+ public:
+ CRibbon() : m_cRef(1), m_pRibbonFramework(NULL) {}
+ ~CRibbon();
+
+ // IUnknown methods.
+ STDMETHOD_(ULONG, AddRef());
+ STDMETHOD_(ULONG, Release());
+ STDMETHOD(QueryInterface(REFIID iid, void** ppv));
+
+ // IUIApplication methods
+ STDMETHOD(OnCreateUICommand)(UINT nCmdID, __in UI_COMMANDTYPE typeID,
+ __deref_out IUICommandHandler** ppCommandHandler);
+
+ STDMETHOD(OnDestroyUICommand)(UINT32 commandId, __in UI_COMMANDTYPE typeID,
+ __in_opt IUICommandHandler* commandHandler);
+
+ STDMETHOD(OnViewChanged)(UINT viewId, __in UI_VIEWTYPE typeId, __in IUnknown* pView,
+ UI_VIEWVERB verb, INT uReasonCode);
+
+ // IUICommandHandle methods
+ STDMETHODIMP Execute(UINT nCmdID, UI_EXECUTIONVERB verb, __in_opt const PROPERTYKEY* key, __in_opt const PROPVARIANT* ppropvarValue,
+ __in_opt IUISimplePropertySet* pCommandExecutionProperties);
+
+ STDMETHODIMP UpdateProperty(UINT nCmdID, __in REFPROPERTYKEY key, __in_opt const PROPVARIANT* ppropvarCurrentValue,
+ __out PROPVARIANT* ppropvarNewValue);
+
+ bool virtual CreateRibbon(CWnd* pWnd);
+ void virtual DestroyRibbon();
+ IUIFramework* GetRibbonFramework() { return m_pRibbonFramework; }
+
+ private:
+ IUIFramework* m_pRibbonFramework;
+ LONG m_cRef; // Reference count.
+
+ };
+
+
+ class CRibbonFrame : public CFrame, public CRibbon
+ {
+ public:
+ // A nested class for the MRU item properties
+ class CRecentFiles : public IUISimplePropertySet
+ {
+ public:
+ CRecentFiles(PWSTR wszFullPath);
+ ~CRecentFiles() {}
+
+ // IUnknown methods.
+ STDMETHODIMP_(ULONG) AddRef();
+ STDMETHODIMP_(ULONG) Release();
+ STDMETHODIMP QueryInterface(REFIID iid, void** ppv);
+
+ // IUISimplePropertySet methods
+ STDMETHODIMP GetValue(__in REFPROPERTYKEY key, __out PROPVARIANT *value);
+
+ private:
+ LONG m_cRef; // Reference count.
+ WCHAR m_wszDisplayName[MAX_PATH];
+ WCHAR m_wszFullPath[MAX_PATH];
+ };
+
+ typedef Shared_Ptr<CRecentFiles> RecentFilesPtr;
+
+ CRibbonFrame() : m_uRibbonHeight(0) {}
+ virtual ~CRibbonFrame() {}
+ virtual CRect GetViewRect() const;
+ virtual void OnCreate();
+ virtual void OnDestroy();
+ virtual STDMETHODIMP OnViewChanged(UINT32 viewId, UI_VIEWTYPE typeId, IUnknown* pView, UI_VIEWVERB verb, INT32 uReasonCode);
+ virtual HRESULT PopulateRibbonRecentItems(__deref_out PROPVARIANT* pvarValue);
+ virtual void UpdateMRUMenu();
+
+ UINT GetRibbonHeight() const { return m_uRibbonHeight; }
+
+ private:
+ std::vector<RecentFilesPtr> m_vRecentFiles;
+ void SetRibbonHeight(UINT uRibbonHeight) { m_uRibbonHeight = uRibbonHeight; }
+ UINT m_uRibbonHeight;
+ };
+
+}
+
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+namespace Win32xx
+{
+ //////////////////////////////////////////////
+ // Definitions for the CRibbon class
+ //
+
+ inline CRibbon::~CRibbon()
+ {
+ // Reference count must be 1 or we have a leak!
+ assert(m_cRef == 1);
+ }
+
+ // IUnknown method implementations.
+ inline STDMETHODIMP_(ULONG) CRibbon::AddRef()
+ {
+ return InterlockedIncrement(&m_cRef);
+ }
+
+ inline STDMETHODIMP_(ULONG) CRibbon::Release()
+ {
+ LONG cRef = InterlockedDecrement(&m_cRef);
+ return cRef;
+ }
+
+ inline STDMETHODIMP CRibbon::Execute(UINT nCmdID, UI_EXECUTIONVERB verb, __in_opt const PROPERTYKEY* key, __in_opt const PROPVARIANT* ppropvarValue,
+ __in_opt IUISimplePropertySet* pCommandExecutionProperties)
+ {
+ UNREFERENCED_PARAMETER (nCmdID);
+ UNREFERENCED_PARAMETER (verb);
+ UNREFERENCED_PARAMETER (key);
+ UNREFERENCED_PARAMETER (ppropvarValue);
+ UNREFERENCED_PARAMETER (pCommandExecutionProperties);
+
+ return E_NOTIMPL;
+ }
+
+ inline STDMETHODIMP CRibbon::QueryInterface(REFIID iid, void** ppv)
+ {
+ if (iid == __uuidof(IUnknown))
+ {
+ *ppv = static_cast<IUnknown*>(static_cast<IUIApplication*>(this));
+ }
+ else if (iid == __uuidof(IUICommandHandler))
+ {
+ *ppv = static_cast<IUICommandHandler*>(this);
+ }
+ else if (iid == __uuidof(IUIApplication))
+ {
+ *ppv = static_cast<IUIApplication*>(this);
+ }
+ else
+ {
+ *ppv = NULL;
+ return E_NOINTERFACE;
+ }
+
+ AddRef();
+ return S_OK;
+ }
+
+ // Called by the Ribbon framework for each command specified in markup, to bind the Command to an IUICommandHandler.
+ inline STDMETHODIMP CRibbon::OnCreateUICommand(UINT nCmdID, __in UI_COMMANDTYPE typeID,
+ __deref_out IUICommandHandler** ppCommandHandler)
+ {
+ UNREFERENCED_PARAMETER(typeID);
+ UNREFERENCED_PARAMETER(nCmdID);
+
+ // By default we use the single command handler provided as part of CRibbon.
+ // Override this function to account for multiple command handlers.
+
+ return QueryInterface(IID_PPV_ARGS(ppCommandHandler));
+ }
+
+ // Called when the state of the Ribbon changes, for example, created, destroyed, or resized.
+ inline STDMETHODIMP CRibbon::OnViewChanged(UINT viewId, __in UI_VIEWTYPE typeId, __in IUnknown* pView,
+ UI_VIEWVERB verb, INT uReasonCode)
+ {
+ UNREFERENCED_PARAMETER(viewId);
+ UNREFERENCED_PARAMETER(typeId);
+ UNREFERENCED_PARAMETER(pView);
+ UNREFERENCED_PARAMETER(verb);
+ UNREFERENCED_PARAMETER(uReasonCode);
+
+
+ return E_NOTIMPL;
+ }
+
+ // Called by the Ribbon framework for each command at the time of ribbon destruction.
+ inline STDMETHODIMP CRibbon::OnDestroyUICommand(UINT32 nCmdID, __in UI_COMMANDTYPE typeID,
+ __in_opt IUICommandHandler* commandHandler)
+ {
+ UNREFERENCED_PARAMETER(commandHandler);
+ UNREFERENCED_PARAMETER(typeID);
+ UNREFERENCED_PARAMETER(nCmdID);
+
+ return E_NOTIMPL;
+ }
+
+ // Called by the Ribbon framework when a command property (PKEY) needs to be updated.
+ inline STDMETHODIMP CRibbon::UpdateProperty(UINT nCmdID, __in REFPROPERTYKEY key, __in_opt const PROPVARIANT* ppropvarCurrentValue,
+ __out PROPVARIANT* ppropvarNewValue)
+ {
+ UNREFERENCED_PARAMETER(nCmdID);
+ UNREFERENCED_PARAMETER(key);
+ UNREFERENCED_PARAMETER(ppropvarCurrentValue);
+ UNREFERENCED_PARAMETER(ppropvarNewValue);
+
+ return E_NOTIMPL;
+ }
+
+ inline bool CRibbon::CreateRibbon(CWnd* pWnd)
+ {
+ ::CoInitialize(NULL);
+
+ // Instantiate the Ribbon framework object.
+ ::CoCreateInstance(CLSID_UIRibbonFramework, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&m_pRibbonFramework));
+
+ // Connect the host application to the Ribbon framework.
+ HRESULT hr = m_pRibbonFramework->Initialize(pWnd->GetHwnd(), this);
+ if (FAILED(hr))
+ {
+ return false;
+ }
+
+ // Load the binary markup. APPLICATION_RIBBON is the default name generated by uicc.
+ hr = m_pRibbonFramework->LoadUI(GetModuleHandle(NULL), L"APPLICATION_RIBBON");
+ if (FAILED(hr))
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ inline void CRibbon::DestroyRibbon()
+ {
+ if (m_pRibbonFramework)
+ {
+ m_pRibbonFramework->Destroy();
+ m_pRibbonFramework->Release();
+ m_pRibbonFramework = NULL;
+ }
+ }
+
+
+ //////////////////////////////////////////////
+ // Definitions for the CRibbonFrame class
+ //
+
+ inline CRect CRibbonFrame::GetViewRect() const
+ {
+ // Get the frame's client area
+ CRect rcFrame = GetClientRect();
+
+ // Get the statusbar's window area
+ CRect rcStatus;
+ if (GetStatusBar().IsWindowVisible() || !IsWindowVisible())
+ rcStatus = GetStatusBar().GetWindowRect();
+
+ // Get the top rebar or toolbar's window area
+ CRect rcTop;
+ if (IsReBarSupported() && m_bUseReBar)
+ rcTop = GetReBar().GetWindowRect();
+ else
+ if (m_bUseToolBar && GetToolBar().IsWindowVisible())
+ rcTop = GetToolBar().GetWindowRect();
+
+ // Return client size less the rebar and status windows
+ int top = rcFrame.top + rcTop.Height() + m_uRibbonHeight;
+ int left = rcFrame.left;
+ int right = rcFrame.right;
+ int bottom = rcFrame.Height() - (rcStatus.Height());
+ if ((bottom <= top) ||( right <= left))
+ top = left = right = bottom = 0;
+
+ CRect rcView(left, top, right, bottom);
+ return rcView;
+ }
+
+ inline void CRibbonFrame::OnCreate()
+ {
+ // OnCreate is called automatically during window creation when a
+ // WM_CREATE message received.
+
+ // Tasks such as setting the icon, creating child windows, or anything
+ // associated with creating windows are normally performed here.
+
+ if (GetWinVersion() >= 2601) // WinVersion >= Windows 7
+ {
+ m_bUseReBar = FALSE; // Don't use rebars
+ m_bUseToolBar = FALSE; // Don't use a toolbar
+
+ CFrame::OnCreate();
+
+ if (CreateRibbon(this))
+ TRACE(_T("Ribbon Created Succesfully\n"));
+ else
+ throw CWinException(_T("Failed to create ribbon"));
+ }
+ else
+ {
+ CFrame::OnCreate();
+ }
+ }
+
+ inline void CRibbonFrame::OnDestroy()
+ {
+ DestroyRibbon();
+ CFrame::OnDestroy();
+ }
+
+ inline STDMETHODIMP CRibbonFrame::OnViewChanged(UINT32 viewId, UI_VIEWTYPE typeId, IUnknown* pView, UI_VIEWVERB verb, INT32 uReasonCode)
+ {
+ UNREFERENCED_PARAMETER(viewId);
+ UNREFERENCED_PARAMETER(uReasonCode);
+
+ HRESULT hr = E_NOTIMPL;
+
+ // Checks to see if the view that was changed was a Ribbon view.
+ if (UI_VIEWTYPE_RIBBON == typeId)
+ {
+ switch (verb)
+ {
+ // The view was newly created.
+ case UI_VIEWVERB_CREATE:
+ hr = S_OK;
+ break;
+
+ // The view has been resized. For the Ribbon view, the application should
+ // call GetHeight to determine the height of the ribbon.
+ case UI_VIEWVERB_SIZE:
+ {
+ IUIRibbon* pRibbon = NULL;
+ UINT uRibbonHeight;
+
+ hr = pView->QueryInterface(IID_PPV_ARGS(&pRibbon));
+ if (SUCCEEDED(hr))
+ {
+ // Call to the framework to determine the desired height of the Ribbon.
+ hr = pRibbon->GetHeight(&uRibbonHeight);
+ SetRibbonHeight(uRibbonHeight);
+ pRibbon->Release();
+
+ RecalcLayout();
+ // Use the ribbon height to position controls in the client area of the window.
+ }
+ }
+ break;
+ // The view was destroyed.
+ case UI_VIEWVERB_DESTROY:
+ hr = S_OK;
+ break;
+ }
+ }
+
+ return hr;
+ }
+
+ inline HRESULT CRibbonFrame::PopulateRibbonRecentItems(__deref_out PROPVARIANT* pvarValue)
+ {
+ LONG iCurrentFile = 0;
+ std::vector<tString> FileNames = GetMRUEntries();
+ std::vector<tString>::iterator iter;
+ int iFileCount = FileNames.size();
+ HRESULT hr = E_FAIL;
+ SAFEARRAY* psa = SafeArrayCreateVector(VT_UNKNOWN, 0, iFileCount);
+ m_vRecentFiles.clear();
+
+ if (psa != NULL)
+ {
+ for (iter = FileNames.begin(); iter < FileNames.end(); ++iter)
+ {
+ tString strCurrentFile = (*iter);
+ WCHAR wszCurrentFile[MAX_PATH] = {0L};
+ lstrcpynW(wszCurrentFile, T2W(strCurrentFile.c_str()), MAX_PATH);
+
+ CRecentFiles* pRecentFiles = new CRecentFiles(wszCurrentFile);
+ m_vRecentFiles.push_back(RecentFilesPtr(pRecentFiles));
+ hr = SafeArrayPutElement(psa, &iCurrentFile, static_cast<void*>(pRecentFiles));
+ ++iCurrentFile;
+ }
+
+ SAFEARRAYBOUND sab = {iCurrentFile,0};
+ SafeArrayRedim(psa, &sab);
+ hr = UIInitPropertyFromIUnknownArray(UI_PKEY_RecentItems, psa, pvarValue);
+
+ SafeArrayDestroy(psa); // Calls release for each element in the array
+ }
+
+ return hr;
+ }
+
+ inline void CRibbonFrame::UpdateMRUMenu()
+ {
+ // Suppress UpdateMRUMenu when ribbon is used
+ if (0 != GetRibbonFramework()) return;
+
+ CFrame::UpdateMRUMenu();
+ }
+
+
+ ////////////////////////////////////////////////////////
+ // Declaration of the nested CRecentFiles class
+ //
+ inline CRibbonFrame::CRecentFiles::CRecentFiles(PWSTR wszFullPath) : m_cRef(1)
+ {
+ SHFILEINFOW sfi;
+ DWORD_PTR dwPtr = NULL;
+ m_wszFullPath[0] = L'\0';
+ m_wszDisplayName[0] = L'\0';
+
+ if (NULL != lstrcpynW(m_wszFullPath, wszFullPath, MAX_PATH))
+ {
+ dwPtr = ::SHGetFileInfoW(wszFullPath, FILE_ATTRIBUTE_NORMAL, &sfi, sizeof(sfi), SHGFI_DISPLAYNAME | SHGFI_USEFILEATTRIBUTES);
+
+ if (dwPtr != NULL)
+ {
+ lstrcpynW(m_wszDisplayName, sfi.szDisplayName, MAX_PATH);
+ }
+ else // Provide a reasonable fallback.
+ {
+ lstrcpynW(m_wszDisplayName, m_wszFullPath, MAX_PATH);
+ }
+ }
+ }
+
+ inline STDMETHODIMP_(ULONG) CRibbonFrame::CRecentFiles::AddRef()
+ {
+ return InterlockedIncrement(&m_cRef);
+ }
+
+ inline STDMETHODIMP_(ULONG) CRibbonFrame::CRecentFiles::Release()
+ {
+ return InterlockedDecrement(&m_cRef);
+ }
+
+ inline STDMETHODIMP CRibbonFrame::CRecentFiles::QueryInterface(REFIID iid, void** ppv)
+ {
+ if (!ppv)
+ {
+ return E_POINTER;
+ }
+
+ if (iid == __uuidof(IUnknown))
+ {
+ *ppv = static_cast<IUnknown*>(this);
+ }
+ else if (iid == __uuidof(IUISimplePropertySet))
+ {
+ *ppv = static_cast<IUISimplePropertySet*>(this);
+ }
+ else
+ {
+ *ppv = NULL;
+ return E_NOINTERFACE;
+ }
+
+ AddRef();
+ return S_OK;
+ }
+
+ // IUISimplePropertySet methods.
+ inline STDMETHODIMP CRibbonFrame::CRecentFiles::GetValue(__in REFPROPERTYKEY key, __out PROPVARIANT *ppropvar)
+ {
+ HRESULT hr = HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
+
+ if (key == UI_PKEY_Label)
+ {
+ hr = UIInitPropertyFromString(key, m_wszDisplayName, ppropvar);
+ }
+ else if (key == UI_PKEY_LabelDescription)
+ {
+ hr = UIInitPropertyFromString(key, m_wszDisplayName, ppropvar);
+ }
+
+ return hr;
+ }
+
+} // namespace Win32xx
+
+#endif // _WIN32XX_RIBBON_H_
+
diff --git a/mmc_updater/depends/win32cpp/shared_ptr.h b/mmc_updater/depends/win32cpp/shared_ptr.h
new file mode 100644
index 00000000..0d2f8b0c
--- /dev/null
+++ b/mmc_updater/depends/win32cpp/shared_ptr.h
@@ -0,0 +1,199 @@
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
+// OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// This software was developed from code available in the public domain
+// and has no copyright.
+
+
+// About Shared_Ptr:
+// Shared_Ptr wraps a reference-counted smart pointer around a dynamically
+// allocated object. Unlike auto_ptr, the Shared_Ptr can be used as a smart
+// pointer for objects stored in containers like std::vector. Do not use
+// Shared_Ptr (or shared_ptr or auto_ptr) for dynamically allocated arrays.
+// See below for advice on how to wrap dynamically allocated arrays in a
+// vector.
+//
+// The next standard of C++ will also contain a shared_ptr. Some modern
+// compilers already have a shared_ptr available as std::tr1::shared_ptr. If
+// your compiler already provides a shared_ptr, or if you have Boost, you
+// should use that smart pointer instead. This class has been provided for
+// those users who don't have easy access to an "official" shared_ptr.
+// Note that this class is "Shared_Ptr", a slightly different name to the
+// future "shared_ptr" to avoid naming conflicts.
+
+// Advantages of Shared_Ptr (or shared_ptr where available):
+// - Shared_Ptr can be safely copied. This makes then suitable for containers.
+// - Shared_Ptr automatically calls delete for the wrapped pointer when
+// its last copy goes out of scope.
+// - Shared_Ptr simplifies exception safety.
+//
+// Without smart pointers, it can be quite challenging to ensure that every
+// dynamically allocated pointer (i.e. use of new) is deleted in the event of
+// all possible exceptions. In addition to the exceptions we throw ourselves,
+// "new" itself will throw an exception it it fails, as does the STL (Standard
+// Template Library which includes vector and string). Without smart pointers
+// we often need to resort to additional try/catch blocks simply to avoid
+// memory leaks when exceptions occur.
+
+// Examples:
+// Shared_Ptr<CWnd> w1(new CWnd);
+// or
+// Shared_Ptr<CWnd> w1 = new CWnd;
+// or
+// typedef Shared_Ptr<CWnd> CWndPtr;
+// CWndPtr w1 = new CWnd;
+// or
+// typedef Shared_Ptr<CWnd> CWndPtr;
+// CWndPtr w1(new CWnd);
+//
+// And with a vector
+// typedef Shared_Ptr<CWnd> CWndPtr;
+// std::vector<CWndPtr> MyVector;
+// MyVector.push_back(new CWnd);
+// or
+// typedef Shared_Ptr<CWnd> CWndPtr;
+// CWnd* pWnd = new CWnd;
+// std::vector<CWndPtr> MyVector;
+// MyVector.push_back(pWnd);
+//
+
+// How to handle dynamically allocated arrays:
+// While we could create a smart pointer for arrays, we don't need to because
+// std::vector already handles this for us. Consider the following example:
+// int nLength = ::GetWindowTextLength(m_hWnd);
+// pTChar = new TCHAR[nLength+1];
+// memset(pTChar, 0, (nLength+1)*sizeof(TCHAR));
+// ::GetWindowText(m_hWnd, m_pTChar, nLength+1);
+// ....
+// delete[] pTChar;
+//
+// This can be improved by using a vector instead of an array
+// int nLength = ::GetWindowTextLength(m_hWnd);
+// std::vector<TCHAR> vTChar( nLength+1, _T('\0') );
+// TCHAR* pTCharArray = &vTChar.front();
+// ::GetWindowText(m_hWnd, pTCharArray, nLength+1);
+//
+// This works because the memory in a vector is always contiguous. Note that
+// this is NOT always true of std::string.
+
+
+// Summing up:
+// In my opinion, "naked" pointers for dynamically created objects should be
+// avoided in modern C++ code. That's to say that calls to "new" should be
+// wrapped in some sort of smart pointer wherever possible. This eliminates
+// the possibility of memory leaks (particularly in the event of exceptions).
+// It also elminiates the need for delete in user's code.
+
+#ifndef _WIN32XX_SHARED_PTR_
+#define _WIN32XX_SHARED_PTR_
+
+namespace Win32xx
+{
+
+ template <class T1>
+ class Shared_Ptr
+ {
+ public:
+ Shared_Ptr() : m_ptr(NULL), m_count(NULL) { }
+ Shared_Ptr(T1 * p) : m_ptr(p), m_count(NULL)
+ {
+ try
+ {
+ if (m_ptr) m_count = new long(0);
+ inc_ref();
+ }
+ // catch the unlikely event of 'new long(0)' throwing an exception
+ catch (const std::bad_alloc&)
+ {
+ delete m_ptr;
+ throw;
+ }
+ }
+ Shared_Ptr(const Shared_Ptr& rhs) : m_ptr(rhs.m_ptr), m_count(rhs.m_count) { inc_ref(); }
+ ~Shared_Ptr()
+ {
+ if(m_count && 0 == dec_ref())
+ {
+ // Note: This code doesn't handle a pointer to an array.
+ // We would need delete[] m_ptr to handle that.
+ delete m_ptr;
+ delete m_count;
+ }
+ }
+
+ T1* get() const { return m_ptr; }
+ long use_count() const { return m_count? *m_count : 0; }
+ bool unique() const { return (m_count && (*m_count == 1)); }
+
+ void swap(Shared_Ptr& rhs)
+ {
+ std::swap(m_ptr, rhs.m_ptr);
+ std::swap(m_count, rhs.m_count);
+ }
+
+ Shared_Ptr& operator=(const Shared_Ptr& rhs)
+ {
+ Shared_Ptr tmp(rhs);
+ this->swap(tmp);
+ return *this;
+ }
+
+ T1* operator->() const
+ {
+ assert(m_ptr);
+ return m_ptr;
+ }
+
+ T1& operator*() const
+ {
+ assert (m_ptr);
+ return *m_ptr;
+ }
+
+ bool operator== (const Shared_Ptr& rhs) const
+ {
+ return ( *m_ptr == *rhs.m_ptr);
+ }
+
+ bool operator!= (const Shared_Ptr& rhs) const
+ {
+ return ( *m_ptr != *rhs.m_ptr);
+ }
+
+ bool operator< (const Shared_Ptr& rhs) const
+ {
+ return ( *m_ptr < *rhs.m_ptr );
+ }
+
+ bool operator> (const Shared_Ptr& rhs) const
+ {
+ return ( *m_ptr > *rhs.m_ptr );
+ }
+
+ private:
+ void inc_ref()
+ {
+ if(m_count)
+ InterlockedIncrement(m_count);
+ }
+
+ int dec_ref()
+ {
+ assert (m_count);
+ return InterlockedDecrement(m_count);
+ }
+
+ T1* m_ptr;
+ long* m_count;
+ };
+
+}
+
+#endif // _WIN32XX_SHARED_PTR_
diff --git a/mmc_updater/depends/win32cpp/socket.h b/mmc_updater/depends/win32cpp/socket.h
new file mode 100644
index 00000000..63a7770f
--- /dev/null
+++ b/mmc_updater/depends/win32cpp/socket.h
@@ -0,0 +1,778 @@
+// Win32++ Version 7.2
+// Released: 5th AUgust 2011
+//
+// David Nash
+// email: dnash@bigpond.net.au
+// url: https://sourceforge.net/projects/win32-framework
+//
+//
+// Copyright (c) 2005-2011 David Nash
+//
+// Permission is hereby granted, free of charge, to
+// any person obtaining a copy of this software and
+// associated documentation files (the "Software"),
+// to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify,
+// merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom
+// the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice
+// shall be included in all copies or substantial portions
+// of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
+// OR OTHER DEALINGS IN THE SOFTWARE.
+//
+////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////
+// socket.h
+// Declaration of the CSocket class
+//
+// The CSocket class represents a network socket. It encapsualtes many of
+// the Windows Socket SPI fuctions, providing an object-oriented approach
+// to network programming. After StartEvents is called, CSocket monitors
+// the socket and responds automatically to network events. This event
+// monitoring, for example, automatically calls OnReceive when there is
+// data on the socket to be read, and OnAccept when a server should accept
+// a connection from a client.
+
+// Users of this class should be aware that functions like OnReceive,
+// OnAccept, etc. are called on a different thread from the one CSocket is
+// instanciated on. The thread for these functions needs to respond quickly
+// to other network events, so it shouldn't be delayed. It also doesn't run
+// a message loop, so it can't be used to create windows. For these reasons
+// it might be best to use PostMessage in response to these functions in a
+// windows environment.
+
+// Refer to the network samples for an example of how to use this class to
+// create a TCP client & server, and a UDP client and server.
+
+// To compile programs with CSocket, link with ws3_32.lib for Win32,
+// and ws2.lib for Windows CE. Windows 95 systems will need to install the
+// "Windows Sockets 2.0 for Windows 95". It's available from:
+// http://support.microsoft.com/kb/182108/EN-US/
+
+// For a TCP server, inherit a class from CSocket and override OnAccept, OnDisconnect
+// and OnRecieve. Create one instance of this class and use it as a listening socket.
+// The purpose of the listening socket is to detect connections from clients and accept them.
+// For the listening socket, we do the following:
+// 1) Create the socket.
+// 2) Bind an IP address to the socket.
+// 3) Listen on the socket for incoming connection requests.
+// 4) Use StartNotifyRevents to receive notification of network events.
+// 5) Override OnAccept to accept requests on a newly created data CSocket object.
+// 6) Create a new data socket for each client connection accepted.
+// 7) The server socket uses the 'accept' function to accept an incoming connection
+// from this new data socket.
+
+// The purpose of the data socket is to send data to, and recieve data from the client.
+// There will be one data socket for each client accepted by the server.
+// To use it we do the following:
+// * To recieve data from the client, override OnReceive and use Receive.
+// * To send data to use Send.
+// * OnDisconnect can be used to detect when the client is disconnected.
+
+// For a TCP client, inherit from CSocket and override OnReceive and OnDisconnect.
+// Create an instance of this inherited class, and perform the following steps:
+// 1) Create the socket.
+// 2) Connect to the server.
+// 3) Use StartNotifyRevents to receive notification of network events.
+// We are now ready to send and recieve data from the server.
+// * Use Send to send data to the server.
+// * Override OnReceive and use Recieve to receive data from the server
+// * OnDisconnect can be used to detect when the client is disconnected from the server.
+
+// Notes regarding IPv6 support
+// * IPv6 is supported on Windows Vista and above. Windows XP with SP2 provides
+// "experimental" support, which can be enabled by entering "ipv6 install"
+// at a command prompt.
+// * IPv6 is not supported by all compilters and devlopment environments. In
+// particular, it is not supported by Dev-C++ or Borland 5.5. A modern
+// Platform SDK needs to be added to Visual Studio 6 for it to support IPv6.
+// * IsIPV6Supported returns false if either the operating system or the
+// development environment fails to support IPv6.
+//
+
+#ifndef _WIN32XX_SOCKET_H_
+#define _WIN32XX_SOCKET_H_
+
+
+#include "wincore.h"
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#include <process.h>
+
+
+#define THREAD_TIMEOUT 100
+
+
+namespace Win32xx
+{
+
+ typedef int WINAPI GETADDRINFO(LPCSTR, LPCSTR, const struct addrinfo*, struct addrinfo**);
+ typedef void WINAPI FREEADDRINFO(struct addrinfo*);
+
+ class CSocket
+ {
+ public:
+ CSocket();
+ virtual ~CSocket();
+
+ // Operations
+ virtual void Accept(CSocket& rClientSock, struct sockaddr* addr, int* addrlen);
+ virtual int Bind(LPCTSTR addr, LPCTSTR port);
+ virtual int Bind(const struct sockaddr* name, int namelen);
+ virtual int Connect(LPCTSTR addr, LPCTSTR port);
+ virtual int Connect(const struct sockaddr* name, int namelen);
+ virtual BOOL Create( int family, int type, int protocol = IPPROTO_IP);
+ virtual void Disconnect();
+ virtual void FreeAddrInfo( struct addrinfo* ai );
+ virtual int GetAddrInfo( LPCTSTR nodename, LPCTSTR servname, const struct addrinfo* hints, struct addrinfo** res);
+ virtual LPCTSTR GetLastError();
+ virtual int ioCtlSocket(long cmd, u_long* argp);
+ virtual BOOL IsIPV6Supported();
+ virtual int Listen(int backlog = SOMAXCONN);
+ virtual int Receive(TCHAR* buf, int len, int flags);
+ virtual int ReceiveFrom(TCHAR* buf, int len, int flags, struct sockaddr* from, int* fromlen);
+ virtual int Send(LPCTSTR buf, int len, int flags);
+ virtual int SendTo(LPCTSTR send, int len, int flags, LPCTSTR addr, LPCTSTR port);
+ virtual int SendTo(LPCTSTR buf, int len, int flags, const struct sockaddr* to, int tolen);
+
+ virtual void StartEvents();
+ virtual void StopEvents();
+
+ // Attributes
+ virtual int GetPeerName(struct sockaddr* name, int* namelen);
+ virtual int GetSockName(struct sockaddr* name, int* namelen);
+ SOCKET& GetSocket() { return m_Socket; }
+ virtual int GetSockOpt(int level, int optname, char* optval, int* optlen);
+ virtual int SetSockOpt(int level, int optname, const char* optval, int optlen);
+
+ // Override these functions to monitor events
+ virtual void OnAccept() {}
+ virtual void OnAddresListChange() {}
+ virtual void OnDisconnect() {}
+ virtual void OnConnect() {}
+ virtual void OnOutOfBand() {}
+ virtual void OnQualityOfService() {}
+ virtual void OnReceive() {}
+ virtual void OnRoutingChange() {}
+ virtual void OnSend() {}
+
+
+
+ // Allow CSocket to be used as a SOCKET
+ operator SOCKET() const {return m_Socket;}
+
+ private:
+ CSocket(const CSocket&); // Disable copy construction
+ CSocket& operator = (const CSocket&); // Disable assignment operator
+ static UINT WINAPI EventThread(LPVOID thread_data);
+
+ tString m_tsErrorMessage;
+ SOCKET m_Socket;
+ HMODULE m_hWS2_32;
+ HANDLE m_hEventThread; // Handle to the thread
+ HANDLE m_StopRequest; // An event to signal the event thread should stop
+ HANDLE m_Stopped; // An event to signal the event thread is stopped
+
+ GETADDRINFO* m_pfnGetAddrInfo; // pointer for the GetAddrInfo function
+ FREEADDRINFO* m_pfnFreeAddrInfo; // pointer for the FreeAddrInfo function
+ };
+}
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+namespace Win32xx
+{
+
+ inline CSocket::CSocket() : m_Socket(INVALID_SOCKET), m_hEventThread(0)
+ {
+ // Initialise the Windows Socket services
+ WSADATA wsaData;
+
+ if (0 != ::WSAStartup(MAKEWORD(2,2), &wsaData))
+ throw CWinException(_T("WSAStartup failed"));
+
+ m_hWS2_32 = ::LoadLibrary(_T("WS2_32.dll"));
+ if (0 == m_hWS2_32)
+ throw CWinException(_T("Failed to load WS2_2.dll"));
+
+ m_pfnGetAddrInfo = (GETADDRINFO*) GetProcAddress(m_hWS2_32, "getaddrinfo");
+ m_pfnFreeAddrInfo = (FREEADDRINFO*) GetProcAddress(m_hWS2_32, "freeaddrinfo");
+
+ m_StopRequest = ::CreateEvent(0, TRUE, FALSE, 0);
+ m_Stopped = ::CreateEvent(0, TRUE, FALSE, 0);
+ }
+
+ inline CSocket::~CSocket()
+ {
+ Disconnect();
+
+ // Close handles
+ ::CloseHandle(m_StopRequest);
+ ::CloseHandle(m_Stopped);
+
+ // Terminate the Windows Socket services
+ ::WSACleanup();
+
+ ::FreeLibrary(m_hWS2_32);
+ }
+
+ inline void CSocket::Accept(CSocket& rClientSock, struct sockaddr* addr, int* addrlen)
+ {
+ // The accept function permits an incoming connection attempt on the socket.
+
+ rClientSock.m_Socket = ::accept(m_Socket, addr, addrlen);
+ if (INVALID_SOCKET == rClientSock.GetSocket())
+ TRACE(_T("Accept failed\n"));
+ }
+
+ inline int CSocket::Bind(LPCTSTR addr, LPCTSTR port)
+ // The bind function associates a local address with the socket.
+ {
+ int RetVal = 0;
+
+ if (IsIPV6Supported())
+ {
+
+#ifdef GetAddrInfo // Skip the following code block for older development environments
+
+ ADDRINFO Hints= {0};
+ Hints.ai_flags = AI_NUMERICHOST | AI_PASSIVE;
+ ADDRINFO *AddrInfo;
+
+ RetVal = GetAddrInfo(addr, port, &Hints, &AddrInfo);
+ if (RetVal != 0)
+ {
+ TRACE( _T("GetAddrInfo failed\n"));
+ return RetVal;
+ }
+
+ // Bind the IP address to the listening socket
+ RetVal = ::bind( m_Socket, AddrInfo->ai_addr, (int)AddrInfo->ai_addrlen );
+ if ( RetVal == SOCKET_ERROR )
+ {
+ TRACE(_T("Bind failed\n"));
+ return RetVal;
+ }
+
+ // Free the address information allocated by GetAddrInfo
+ FreeAddrInfo(AddrInfo);
+
+#endif
+
+ }
+ else
+ {
+ sockaddr_in clientService;
+ clientService.sin_family = AF_INET;
+ clientService.sin_addr.s_addr = inet_addr( T2A(addr) );
+ int nPort = -1;
+ nPort = atoi( T2A(port) );
+ if (-1 == nPort)
+ {
+ TRACE(_T("Invalid port number\n"));
+ return SOCKET_ERROR;
+ }
+ clientService.sin_port = htons( (u_short)nPort );
+
+ RetVal = ::bind( m_Socket, (SOCKADDR*) &clientService, sizeof(clientService) );
+ if ( 0 != RetVal )
+ TRACE(_T("Bind failed\n"));
+ }
+
+ return RetVal;
+ }
+
+ inline int CSocket::Bind(const struct sockaddr* name, int namelen)
+ {
+ // The bind function associates a local address with the socket.
+
+ int Result = ::bind (m_Socket, name, namelen);
+ if ( 0 != Result )
+ TRACE(_T("Bind failed\n"));
+ return Result;
+ }
+
+ inline int CSocket::Connect(LPCTSTR addr, LPCTSTR port)
+ // The Connect function establishes a connection to the socket.
+ {
+ int RetVal = 0;
+
+ if (IsIPV6Supported())
+ {
+
+#ifdef GetAddrInfo // Skip the following code block for older development environments
+
+ ADDRINFO Hints= {0};
+ Hints.ai_flags = AI_NUMERICHOST | AI_PASSIVE;
+ ADDRINFO *AddrInfo;
+
+ RetVal = GetAddrInfo(addr, port, &Hints, &AddrInfo);
+ if (RetVal != 0)
+ {
+ TRACE( _T("getaddrinfo failed\n"));
+ return SOCKET_ERROR;
+ }
+
+ // Bind the IP address to the listening socket
+ RetVal = Connect( AddrInfo->ai_addr, (int)AddrInfo->ai_addrlen );
+ if ( RetVal == SOCKET_ERROR )
+ {
+ TRACE(_T("Connect failed\n"));
+ return RetVal;
+ }
+
+ // Free the address information allocatied by GetAddrInfo
+ FreeAddrInfo(AddrInfo);
+
+#endif
+
+ }
+ else
+ {
+ sockaddr_in clientService;
+ clientService.sin_family = AF_INET;
+ clientService.sin_addr.s_addr = inet_addr( T2A(addr) );
+ int nPort = -1;
+ nPort = atoi( T2A(port) );
+ if (-1 == nPort)
+ {
+ TRACE(_T("Invalid port number\n"));
+ return SOCKET_ERROR;
+ }
+ clientService.sin_port = htons( (u_short)nPort );
+
+ RetVal = ::connect( m_Socket, (SOCKADDR*) &clientService, sizeof(clientService) );
+ if ( 0 != RetVal )
+ TRACE(_T("Connect failed\n"));
+ }
+
+ return RetVal;
+ }
+
+ inline int CSocket::Connect(const struct sockaddr* name, int namelen)
+ {
+ // The Connect function establishes a connection to the socket.
+
+ int Result = ::connect( m_Socket, name, namelen );
+ if ( 0 != Result )
+ TRACE(_T("Connect failed\n"));
+
+ return Result;
+ }
+
+ inline BOOL CSocket::Create( int family, int type, int protocol /*= IPPROTO_IP*/)
+ {
+ // Creates the socket
+
+ // Valid values:
+ // family: AF_INET or AF_INET6
+ // type: SOCK_DGRAM, SOCK_SEQPACKET, SOCK_STREAM, SOCK_RAW
+ // protocol: IPPROTO_IP, IPPROTO_TCP, IPPROTO_UDP, IPPROTO_RAW, IPPROTO_ICMP, IPPROTO_ICMPV6
+
+ m_Socket = socket(family, type, protocol);
+ if(m_Socket == INVALID_SOCKET)
+ {
+ TRACE(_T("Failed to create socket\n"));
+ return FALSE;
+ }
+
+ return TRUE;
+ }
+
+ inline void CSocket::Disconnect()
+ {
+ ::shutdown(m_Socket, SD_BOTH);
+ StopEvents();
+ ::closesocket(m_Socket);
+ m_Socket = INVALID_SOCKET;
+ }
+
+ inline UINT WINAPI CSocket::EventThread(LPVOID thread_data)
+ {
+ // These are the possible network event notifications:
+ // FD_READ Notification of readiness for reading.
+ // FD_WRITE Motification of readiness for writing.
+ // FD_OOB Notification of the arrival of Out Of Band data.
+ // FD_ACCEPT Notification of incoming connections.
+ // FD_CONNECT Notification of completed connection or multipoint join operation.
+ // FD_CLOSE Notification of socket closure.
+ // FD_QOS Notification of socket Quality Of Service changes
+ // FD_ROUTING_INTERFACE_CHANGE Notification of routing interface changes for the specified destination.
+ // FD_ADDRESS_LIST_CHANGE Notification of local address list changes for the address family of the socket.
+
+ WSANETWORKEVENTS NetworkEvents;
+ CSocket* pSocket = (CSocket*)thread_data;
+ SOCKET sClient = pSocket->m_Socket;
+
+ WSAEVENT AllEvents[2];
+ AllEvents[0] = ::WSACreateEvent();
+ AllEvents[1] = (WSAEVENT)pSocket->m_StopRequest;
+ long Events = FD_READ | FD_WRITE | FD_OOB | FD_ACCEPT | FD_CONNECT | FD_CLOSE |
+ FD_QOS | FD_ROUTING_INTERFACE_CHANGE | FD_ADDRESS_LIST_CHANGE;
+
+ // Associate the network event object (hNetworkEvents) with the
+ // specified network events (Events) on socket sClient.
+ if( SOCKET_ERROR == WSAEventSelect(sClient, AllEvents[0], Events))
+ {
+ TRACE(_T("Error in Event Select\n"));
+ ::SetEvent(pSocket->m_Stopped);
+ ::WSACloseEvent(AllEvents[0]);
+ return 0;
+ }
+
+ // loop until the stop event is set
+ for (;;) // infinite loop
+ {
+ // Wait 100 ms for a network event
+ DWORD dwResult = ::WSAWaitForMultipleEvents(2, AllEvents, FALSE, THREAD_TIMEOUT, FALSE);
+
+ // Check event for stop thread
+ if(::WaitForSingleObject(pSocket->m_StopRequest, 0) == WAIT_OBJECT_0)
+ {
+ ::WSACloseEvent(AllEvents[0]);
+ ::SetEvent(pSocket->m_Stopped);
+ return 0;
+ }
+
+ if (WSA_WAIT_FAILED == dwResult)
+ {
+ TRACE(_T("WSAWaitForMultipleEvents failed\n"));
+ ::WSACloseEvent(AllEvents[0]);
+ ::SetEvent(pSocket->m_Stopped);
+ return 0;
+ }
+
+ // Proceed if a network event occurred
+ if (WSA_WAIT_TIMEOUT != dwResult)
+ {
+
+ if ( SOCKET_ERROR == ::WSAEnumNetworkEvents(sClient, AllEvents[0], &NetworkEvents) )
+ {
+ TRACE(_T("WSAEnumNetworkEvents failed\n"));
+ ::WSACloseEvent(AllEvents[0]);
+ ::SetEvent(pSocket->m_Stopped);
+ return 0;
+ }
+
+ if (NetworkEvents.lNetworkEvents & FD_ACCEPT)
+ pSocket->OnAccept();
+
+ if (NetworkEvents.lNetworkEvents & FD_READ)
+ pSocket->OnReceive();
+
+ if (NetworkEvents.lNetworkEvents & FD_WRITE)
+ pSocket->OnSend();
+
+ if (NetworkEvents.lNetworkEvents & FD_OOB)
+ pSocket->OnOutOfBand();
+
+ if (NetworkEvents.lNetworkEvents & FD_QOS)
+ pSocket->OnQualityOfService();
+
+ if (NetworkEvents.lNetworkEvents & FD_CONNECT)
+ pSocket->OnConnect();
+
+ if (NetworkEvents.lNetworkEvents & FD_ROUTING_INTERFACE_CHANGE)
+ pSocket->OnRoutingChange();
+
+ if (NetworkEvents.lNetworkEvents & FD_ADDRESS_LIST_CHANGE)
+ pSocket->OnAddresListChange();
+
+ if (NetworkEvents.lNetworkEvents & FD_CLOSE)
+ {
+ ::shutdown(sClient, SD_BOTH);
+ ::closesocket(sClient);
+ pSocket->OnDisconnect();
+ ::WSACloseEvent(AllEvents[0]);
+ ::SetEvent(pSocket->m_Stopped);
+ return 0;
+ }
+ }
+ }
+ }
+
+ inline int CSocket::GetAddrInfo( LPCTSTR nodename, LPCTSTR servname, const struct addrinfo* hints, struct addrinfo** res)
+ {
+
+#ifdef GetAddrInfo
+
+ std::string sNodeName = T2A(nodename);
+ std::string sServName = T2A(servname);
+ return (*m_pfnGetAddrInfo)(sNodeName.c_str(), sServName.c_str(), hints, res);
+
+#else
+
+ UNREFERENCED_PARAMETER(nodename);
+ UNREFERENCED_PARAMETER(servname);
+ UNREFERENCED_PARAMETER(hints);
+ UNREFERENCED_PARAMETER(res);
+
+ throw CWinException(_T("getaddrinfo is not supported"));
+
+#endif
+
+ }
+
+ inline LPCTSTR CSocket::GetLastError()
+ {
+ // Retrieves the most recent network error.
+
+ int ErrorCode = WSAGetLastError();
+ LPTSTR Message = NULL;
+ m_tsErrorMessage = _T("");
+
+ FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS |
+ FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_MAX_WIDTH_MASK,
+ NULL, ErrorCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ (LPTSTR)&Message, 1024, NULL);
+
+ if (Message)
+ {
+ m_tsErrorMessage = Message;
+ ::LocalFree(Message);
+ }
+
+ return m_tsErrorMessage.c_str();
+ }
+
+ inline int CSocket::GetPeerName(struct sockaddr* name, int* namelen)
+ {
+ int Result = ::getpeername(m_Socket, name, namelen);
+ if (0 != Result)
+ TRACE(_T("GetPeerName failed\n"));
+
+ return Result;
+ }
+
+ inline int CSocket::GetSockName(struct sockaddr* name, int* namelen)
+ {
+ int Result = ::getsockname(m_Socket, name, namelen);
+ if (0 != Result)
+ TRACE(_T("GetSockName Failed\n"));
+
+ return Result;
+ }
+
+ inline int CSocket::GetSockOpt(int level, int optname, char* optval, int* optlen)
+ {
+ int Result = ::getsockopt(m_Socket, level, optname, optval, optlen);
+ if (0 != Result)
+ TRACE(_T("GetSockOpt Failed\n"));
+
+ return Result;
+ }
+
+ inline void CSocket::FreeAddrInfo( struct addrinfo* ai )
+ {
+
+#ifdef GetAddrInfo
+
+ (*m_pfnFreeAddrInfo)(ai);
+
+#else
+
+ UNREFERENCED_PARAMETER(ai);
+
+ throw CWinException(_T("getaddrinfo is not supported"));
+
+#endif
+
+ }
+
+ inline int CSocket::ioCtlSocket(long cmd, u_long* argp)
+ {
+ int Result = ::ioctlsocket(m_Socket, cmd, argp);
+ if (0 != Result)
+ TRACE(_T("ioCtlSocket Failed\n"));
+
+ return Result;
+ }
+
+ inline BOOL CSocket::IsIPV6Supported()
+ {
+ BOOL IsIPV6Supported = FALSE;
+
+#ifdef GetAddrInfo
+
+ if (m_pfnGetAddrInfo != 0 && m_pfnFreeAddrInfo != 0)
+ IsIPV6Supported = TRUE;
+
+#endif
+
+ return IsIPV6Supported;
+ }
+
+ inline int CSocket::Listen(int backlog /*= SOMAXCONN*/)
+ {
+ int Result = ::listen(m_Socket, backlog);
+ if (0 != Result)
+ TRACE(_T("Listen Failed\n"));
+
+ return Result;
+ }
+
+ inline int CSocket::Receive(TCHAR* buf, int len, int flags)
+ {
+ std::vector<char> vChar(len+1, '\0');
+ char* pCharArray = &vChar.front();
+ int Result = ::recv(m_Socket, pCharArray, len, flags);
+ if (SOCKET_ERROR == Result)
+ TRACE(_T("Receive failed\n"));
+
+ lstrcpyn(buf, A2T(pCharArray), len);
+
+ return Result;
+ }
+
+ inline int CSocket::ReceiveFrom(TCHAR* buf, int len, int flags, struct sockaddr* from, int* fromlen)
+ //The ReceiveFrom function receives a datagram and stores the source address.
+ {
+ std::vector<char> vChar(len+1, '\0');
+ char* pCharArray = &vChar.front();
+ int Result = ::recvfrom(m_Socket, pCharArray, len, flags, from, fromlen);
+ if (SOCKET_ERROR == Result)
+ TRACE(_T("ReceiveFrom failed\n"));
+
+ lstrcpyn(buf, A2T(pCharArray), len);
+
+ return Result;
+ }
+
+ inline int CSocket::Send(LPCTSTR buf, int len, int flags)
+ {
+ int Result = ::send(m_Socket, T2A(buf), len, flags);
+ if (SOCKET_ERROR == Result)
+ TRACE(_T("Send failed\n"));
+
+ return Result;
+ }
+
+ inline int CSocket::SendTo(LPCTSTR send, int len, int flags, LPCTSTR addr, LPCTSTR port)
+ // The sendto function sends data to a specific destination.
+ {
+ int RetVal = 0;
+
+ if (IsIPV6Supported())
+ {
+
+#ifdef GetAddrInfo // Skip the following code block for older development environments
+
+ ADDRINFO Hints= {0};
+ Hints.ai_flags = AI_NUMERICHOST | AI_PASSIVE;
+ ADDRINFO *AddrInfo;
+
+ RetVal = GetAddrInfo(addr, port, &Hints, &AddrInfo);
+ if (RetVal != 0)
+ {
+ TRACE( _T("GetAddrInfo failed\n"));
+ return SOCKET_ERROR;
+ }
+
+ RetVal = ::sendto(m_Socket, T2A(send), len, flags, AddrInfo->ai_addr, (int)AddrInfo->ai_addrlen );
+ if ( RetVal == SOCKET_ERROR )
+ {
+ TRACE(_T("SendTo failed\n"));
+ return RetVal;
+ }
+
+ // Free the address information allocatied by GetAddrInfo
+ FreeAddrInfo(AddrInfo);
+
+#endif
+
+ }
+ else
+ {
+ sockaddr_in clientService;
+ clientService.sin_family = AF_INET;
+ clientService.sin_addr.s_addr = inet_addr( T2A(addr) );
+ int nPort = -1;
+ nPort = atoi( T2A(port));
+ if (-1 == nPort)
+ {
+ TRACE(_T("Invalid port number\n"));
+ return SOCKET_ERROR;
+ }
+ clientService.sin_port = htons( (u_short)nPort );
+
+ RetVal = ::sendto( m_Socket, T2A(send), len, flags, (SOCKADDR*) &clientService, sizeof(clientService) );
+ if ( SOCKET_ERROR != RetVal )
+ TRACE(_T("SendTo failed\n"));
+ }
+
+ return RetVal;
+ }
+
+ inline int CSocket::SendTo(LPCTSTR buf, int len, int flags, const struct sockaddr* to, int tolen)
+ // The sendto function sends data to a specific destination.
+ {
+ int Result = ::sendto(m_Socket, T2A(buf), len, flags, to, tolen);
+ if (SOCKET_ERROR == Result)
+ TRACE(_T("SendTo failed\n"));
+
+ return Result;
+ }
+
+ inline int CSocket::SetSockOpt(int level, int optname, const char* optval, int optlen)
+ {
+ int Result = ::setsockopt(m_Socket, level, optname, optval, optlen);
+ if (0 != Result)
+ TRACE(_T("SetSockOpt failed\n"));
+
+ return Result;
+ }
+
+ inline void CSocket::StartEvents()
+ {
+ // This function starts the thread which monitors the socket for events.
+ StopEvents(); // Ensure the thread isn't already running
+ UINT ThreadID; // a return variable required for Win95, Win98, WinME
+ m_hEventThread = (HANDLE)::_beginthreadex(NULL, 0, CSocket::EventThread, (LPVOID) this, 0, &ThreadID);
+ }
+
+ inline void CSocket::StopEvents()
+ {
+ // Terminates the event thread gracefully (if possible)
+ if (m_hEventThread)
+ {
+ ::SetThreadPriority(m_hEventThread, THREAD_PRIORITY_HIGHEST);
+ ::SetEvent(m_StopRequest);
+
+ for (;;) // infinite loop
+ {
+ // wait for the Thread stopping event to be set
+ if ( WAIT_TIMEOUT == ::WaitForSingleObject(m_Stopped, THREAD_TIMEOUT * 10) )
+ {
+ // Note: An excessive delay in processing any of the notification functions
+ // can cause us to get here. (Yes one second is an excessive delay. Its a bug!)
+ TRACE(_T("*** Error: Event Thread won't die ***\n") );
+ }
+ else break;
+ }
+
+ ::CloseHandle(m_hEventThread);
+ m_hEventThread = 0;
+ }
+
+ ::ResetEvent(m_StopRequest);
+ ::ResetEvent(m_Stopped);
+ }
+}
+
+
+#endif // #ifndef _WIN32XX_SOCKET_H_
+
diff --git a/mmc_updater/depends/win32cpp/statusbar.h b/mmc_updater/depends/win32cpp/statusbar.h
new file mode 100644
index 00000000..ad9a007b
--- /dev/null
+++ b/mmc_updater/depends/win32cpp/statusbar.h
@@ -0,0 +1,226 @@
+// Win32++ Version 7.2
+// Released: 5th AUgust 2011
+//
+// David Nash
+// email: dnash@bigpond.net.au
+// url: https://sourceforge.net/projects/win32-framework
+//
+//
+// Copyright (c) 2005-2011 David Nash
+//
+// Permission is hereby granted, free of charge, to
+// any person obtaining a copy of this software and
+// associated documentation files (the "Software"),
+// to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify,
+// merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom
+// the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice
+// shall be included in all copies or substantial portions
+// of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
+// OR OTHER DEALINGS IN THE SOFTWARE.
+//
+////////////////////////////////////////////////////////
+
+
+#ifndef _WIN32XX_STATUSBAR_H_
+#define _WIN32XX_STATUSBAR_H_
+
+#include "wincore.h"
+
+namespace Win32xx
+{
+
+ //////////////////////////////////////
+ // Declaration of the CStatusBar class
+ //
+ class CStatusBar : public CWnd
+ {
+ public:
+ CStatusBar();
+ virtual ~CStatusBar() {}
+
+ // Overridables
+ virtual void PreCreate(CREATESTRUCT& cs);
+ virtual void PreRegisterClass(WNDCLASS &wc);
+
+ // Attributes
+ int GetParts();
+ HICON GetPartIcon(int iPart);
+ CRect GetPartRect(int iPart);
+ tString GetPartText(int iPart) const;
+ BOOL IsSimple();
+ BOOL SetPartIcon(int iPart, HICON hIcon);
+ BOOL SetPartText(int iPart, LPCTSTR szText, UINT Style = 0) const;
+ BOOL SetPartWidth(int iPart, int iWidth) const;
+
+ // Operations
+ CStatusBar(const CStatusBar&); // Disable copy construction
+ CStatusBar& operator = (const CStatusBar&); // Disable assignment operator
+
+ BOOL CreateParts(int iParts, const int iPaneWidths[]) const;
+ void SetSimple(BOOL fSimple = TRUE);
+ };
+
+}
+
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+namespace Win32xx
+{
+
+ //////////////////////////////////////
+ // Definitions for the CStatusBar class
+ //
+ inline CStatusBar::CStatusBar()
+ {
+ }
+
+ inline BOOL CStatusBar::CreateParts(int iParts, const int iPaneWidths[]) const
+ // Sets the number of parts in a status window and the coordinate of the right edge of each part.
+ // If an element of iPaneWidths is -1, the right edge of the corresponding part extends
+ // to the border of the window
+ {
+ assert(::IsWindow(m_hWnd));
+ assert(iParts <= 256);
+
+ return (BOOL)SendMessage(SB_SETPARTS, iParts, (LPARAM)iPaneWidths);
+ }
+
+ inline int CStatusBar::GetParts()
+ {
+ assert(::IsWindow(m_hWnd));
+ return (int)SendMessage(SB_GETPARTS, 0L, 0L);
+ }
+
+ inline HICON CStatusBar::GetPartIcon(int iPart)
+ {
+ assert(::IsWindow(m_hWnd));
+ return (HICON)SendMessage(SB_GETICON, (WPARAM)iPart, 0L);
+ }
+
+ inline CRect CStatusBar::GetPartRect(int iPart)
+ {
+ assert(::IsWindow(m_hWnd));
+
+ CRect rc;
+ SendMessage(SB_GETRECT, (WPARAM)iPart, (LPARAM)&rc);
+ return rc;
+ }
+
+ inline tString CStatusBar::GetPartText(int iPart) const
+ {
+ assert(::IsWindow(m_hWnd));
+ tString PaneText;
+
+ // Get size of Text array
+ int iChars = LOWORD (SendMessage(SB_GETTEXTLENGTH, iPart, 0L));
+
+ std::vector<TCHAR> Text( iChars +1, _T('\0') );
+ TCHAR* pTextArray = &Text[0];
+
+ SendMessage(SB_GETTEXT, iPart, (LPARAM)pTextArray);
+ PaneText = pTextArray;
+ return PaneText;
+ }
+
+ inline BOOL CStatusBar::IsSimple()
+ {
+ assert(::IsWindow(m_hWnd));
+ return (BOOL)SendMessage(SB_ISSIMPLE, 0L, 0L);
+ }
+
+ inline void CStatusBar::PreCreate(CREATESTRUCT &cs)
+ {
+ cs.style = WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | CCS_BOTTOM | SBARS_SIZEGRIP;
+ }
+
+ inline void CStatusBar::PreRegisterClass(WNDCLASS &wc)
+ {
+ // Set the Window Class
+ wc.lpszClassName = STATUSCLASSNAME;
+ }
+
+ inline BOOL CStatusBar::SetPartText(int iPart, LPCTSTR szText, UINT Style) const
+ // Available Styles: Combinations of ...
+ //0 The text is drawn with a border to appear lower than the plane of the window.
+ //SBT_NOBORDERS The text is drawn without borders.
+ //SBT_OWNERDRAW The text is drawn by the parent window.
+ //SBT_POPOUT The text is drawn with a border to appear higher than the plane of the window.
+ //SBT_RTLREADING The text will be displayed in the opposite direction to the text in the parent window.
+ {
+ assert(::IsWindow(m_hWnd));
+
+ BOOL bResult = FALSE;
+ if (SendMessage(SB_GETPARTS, 0L, 0L) >= iPart)
+ bResult = (BOOL)SendMessage(SB_SETTEXT, iPart | Style, (LPARAM)szText);
+
+ return bResult;
+ }
+
+ inline BOOL CStatusBar::SetPartIcon(int iPart, HICON hIcon)
+ {
+ assert(::IsWindow(m_hWnd));
+ return (BOOL)SendMessage(SB_SETICON, (WPARAM)iPart, (LPARAM) hIcon);
+ }
+
+ inline BOOL CStatusBar::SetPartWidth(int iPart, int iWidth) const
+ {
+ // This changes the width of an existing pane, or creates a new pane
+ // with the specified width.
+ // A width of -1 for the last part sets the width to the border of the window.
+
+ assert(::IsWindow(m_hWnd));
+ assert(iPart >= 0 && iPart <= 255);
+
+ // Fill the PartWidths vector with the current width of the statusbar parts
+ int PartsCount = (int)SendMessage(SB_GETPARTS, 0L, 0L);
+ std::vector<int> PartWidths(PartsCount, 0);
+ int* pPartWidthArray = &PartWidths[0];
+ SendMessage(SB_GETPARTS, PartsCount, (LPARAM)pPartWidthArray);
+
+ // Fill the NewPartWidths vector with the new width of the statusbar parts
+ int NewPartsCount = MAX(iPart+1, PartsCount);
+ std::vector<int> NewPartWidths(NewPartsCount, 0);;
+ NewPartWidths = PartWidths;
+ int* pNewPartWidthArray = &NewPartWidths[0];
+
+ if (0 == iPart)
+ pNewPartWidthArray[iPart] = iWidth;
+ else
+ {
+ if (iWidth >= 0)
+ pNewPartWidthArray[iPart] = pNewPartWidthArray[iPart -1] + iWidth;
+ else
+ pNewPartWidthArray[iPart] = -1;
+ }
+
+ // Set the statusbar parts with our new parts count and part widths
+ BOOL bResult = (BOOL)SendMessage(SB_SETPARTS, NewPartsCount, (LPARAM)pNewPartWidthArray);
+
+ return bResult;
+ }
+
+ inline void CStatusBar::SetSimple(BOOL fSimple /* = TRUE*/)
+ {
+ assert(::IsWindow(m_hWnd));
+ SendMessage(SB_SIMPLE, (WPARAM)fSimple, 0L);
+ }
+
+} // namespace Win32xx
+
+#endif // #ifndef _WIN32XX_STATUSBAR_H_
diff --git a/mmc_updater/depends/win32cpp/stdcontrols.h b/mmc_updater/depends/win32cpp/stdcontrols.h
new file mode 100644
index 00000000..b362f07b
--- /dev/null
+++ b/mmc_updater/depends/win32cpp/stdcontrols.h
@@ -0,0 +1,1000 @@
+// Win32++ Version 7.2
+// Released: 5th AUgust 2011
+//
+// David Nash
+// email: dnash@bigpond.net.au
+// url: https://sourceforge.net/projects/win32-framework
+//
+//
+// Copyright (c) 2005-2011 David Nash
+//
+// Permission is hereby granted, free of charge, to
+// any person obtaining a copy of this software and
+// associated documentation files (the "Software"),
+// to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify,
+// merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom
+// the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice
+// shall be included in all copies or substantial portions
+// of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
+// OR OTHER DEALINGS IN THE SOFTWARE.
+//
+////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////
+// stdcontrols.h
+// Declaration of the CButton, CEdit, CListBox and CStatic classes
+
+// The Button, Edit, ListBox and Static controls are often referred to
+// as "standard controls". These set of older controls were originally
+// developed for Win16 operating systems (Windows 3.1 and 3.11). They use an
+// older form of notification, and send their notifications via a WM_COMMAND
+// message. Newer controls send their notifications via a WM_NOTIFY message.
+
+
+#ifndef _WIN32XX_STDCONTROLS_H_
+#define _WIN32XX_STDCONTROLS_H_
+
+#include "wincore.h"
+
+
+namespace Win32xx
+{
+ class CButton : public CWnd
+ {
+ public:
+ CButton() {}
+ virtual ~CButton() {}
+
+ // Attributes
+ HBITMAP GetBitmap() const;
+ UINT GetButtonStyle() const;
+ int GetCheck() const;
+ HCURSOR GetCursor() const;
+ HICON GetIcon() const;
+ UINT GetState() const;
+ HBITMAP SetBitmap(HBITMAP hBitmap) const;
+ void SetButtonStyle(DWORD dwStyle, BOOL bRedraw) const;
+ void SetCheck(int nCheckState) const;
+ HCURSOR SetCursor(HCURSOR hCursor) const;
+ HICON SetIcon(HICON hIcon) const;
+ void SetState(BOOL bHighlight) const;
+
+ protected:
+ // Overridables
+ virtual void PreCreate(CREATESTRUCT& cs);
+ };
+
+ class CEdit : public CWnd
+ {
+ public:
+ // Construction
+ CEdit() {}
+ virtual ~CEdit() {}
+
+ // Attributes
+ BOOL CanUndo() const;
+ int CharFromPos(CPoint pt) const;
+ int GetFirstVisibleLine() const;
+ HLOCAL GetHandle() const;
+ UINT GetLimitText() const;
+ int GetLine(int nIndex, LPTSTR lpszBuffer) const;
+ int GetLine(int nIndex, LPTSTR lpszBuffer, int nMaxLength) const;
+ int GetLineCount() const;
+ DWORD GetMargins() const;
+ BOOL GetModify() const;
+ TCHAR GetPasswordChar() const;
+ void GetRect(LPRECT lpRect) const;
+ void GetSel(int& nStartChar, int& nEndChar) const;
+ DWORD GetSel() const;
+ CPoint PosFromChar(UINT nChar) const;
+ void SetHandle(HLOCAL hBuffer) const;
+ void SetLimitText(UINT nMax) const;
+ void SetMargins(UINT nLeft, UINT nRight) const;
+ void SetModify(BOOL bModified = TRUE) const;
+
+ // Operations
+ void EmptyUndoBuffer() const;
+ BOOL FmtLines(BOOL bAddEOL) const;
+ void LimitText(int nChars = 0) const;
+ int LineFromChar(int nIndex = -1) const;
+ int LineIndex(int nLine = -1) const;
+ int LineLength(int nLine = -1) const;
+ void LineScroll(int nLines, int nChars = 0) const;
+ void ReplaceSel(LPCTSTR lpszNewText, BOOL bCanUndo) const;
+ void SetPasswordChar(TCHAR ch) const;
+ BOOL SetReadOnly(BOOL bReadOnly = TRUE) const;
+ void SetRect(LPCRECT lpRect) const;
+ void SetRectNP(LPCRECT lpRect) const;
+ void SetSel(DWORD dwSelection, BOOL bNoScroll) const;
+ void SetSel(int nStartChar, int nEndChar, BOOL bNoScroll) const;
+ BOOL SetTabStops(int nTabStops, LPINT rgTabStops) const;
+ BOOL SetTabStops() const;
+ BOOL SetTabStops(const int& cxEachStop) const;
+
+ //Clipboard Operations
+ void Clear() const;
+ void Copy() const;
+ void Cut() const;
+ void Paste() const;
+ void Undo() const;
+
+ protected:
+ // Overridables
+ virtual void PreRegisterClass(WNDCLASS &wc);
+ };
+
+ class CListBox : public CWnd
+ {
+ public:
+ CListBox() {}
+ virtual ~CListBox() {}
+
+ // General Operations
+ int GetCount() const;
+ int GetHorizontalExtent() const;
+ DWORD GetItemData(int nIndex) const;
+ void* GetItemDataPtr(int nIndex) const;
+ int GetItemHeight(int nIndex) const;
+ int GetItemRect(int nIndex, LPRECT lpRect) const;
+ LCID GetLocale() const;
+ int GetSel(int nIndex) const;
+ int GetText(int nIndex, LPTSTR lpszBuffer) const;
+ int GetTextLen(int nIndex) const;
+ int GetTopIndex() const;
+ UINT ItemFromPoint(CPoint pt, BOOL& bOutside ) const;
+ void SetColumnWidth(int cxWidth) const;
+ void SetHorizontalExtent(int cxExtent) const;
+ int SetItemData(int nIndex, DWORD dwItemData) const;
+ int SetItemDataPtr(int nIndex, void* pData) const;
+ int SetItemHeight(int nIndex, UINT cyItemHeight) const;
+ LCID SetLocale(LCID nNewLocale) const;
+ BOOL SetTabStops(int nTabStops, LPINT rgTabStops) const;
+ void SetTabStops() const;
+ BOOL SetTabStops(const int& cxEachStop) const;
+ int SetTopIndex(int nIndex) const;
+
+ // Single-Selection Operations
+ int GetCurSel() const;
+ int SetCurSel(int nSelect) const;
+
+ // Multiple-Selection Operations
+ int GetAnchorIndex() const;
+ int GetCaretIndex() const;
+ int GetSelCount() const;
+ int GetSelItems(int nMaxItems, LPINT rgIndex) const;
+ int SelItemRange(BOOL bSelect, int nFirstItem, int nLastItem) const;
+ void SetAnchorIndex(int nIndex) const;
+ int SetCaretIndex(int nIndex, BOOL bScroll) const;
+ int SetSel(int nIndex, BOOL bSelect) const;
+
+ // String Operations
+ int AddString(LPCTSTR lpszItem) const;
+ int DeleteString(UINT nIndex) const;
+ int Dir(UINT attr, LPCTSTR lpszWildCard) const;
+ int FindString(int nStartAfter, LPCTSTR lpszItem) const;
+ int FindStringExact(int nIndexStart, LPCTSTR lpszFind) const;
+ int InsertString(int nIndex, LPCTSTR lpszItem) const;
+ void ResetContent() const;
+ int SelectString(int nStartAfter, LPCTSTR lpszItem) const;
+
+ protected:
+ // Overridables
+ virtual void PreRegisterClass(WNDCLASS &wc);
+ };
+
+ class CStatic : public CWnd
+ {
+ public:
+ CStatic() {}
+ virtual ~CStatic() {}
+
+ // Operations
+ HBITMAP GetBitmap() const;
+ HCURSOR GetCursor() const;
+ HENHMETAFILE GetEnhMetaFile() const;
+ HICON GetIcon() const;
+ HBITMAP SetBitmap(HBITMAP hBitmap) const;
+ HCURSOR SetCursor(HCURSOR hCursor) const;
+ HENHMETAFILE SetEnhMetaFile(HENHMETAFILE hMetaFile) const;
+ HICON SetIcon(HICON hIcon) const;
+
+ protected:
+ // Overridables
+ virtual void PreRegisterClass(WNDCLASS &wc);
+
+ };
+
+}
+
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+namespace Win32xx
+{
+
+ ////////////////////////////////////////
+ // Definitions for the CButton class
+ //
+ inline HBITMAP CButton::GetBitmap() const
+ // returns the handle to the bitmap associated with the button
+ {
+ assert(::IsWindow(m_hWnd));
+ return (HBITMAP)SendMessage(BM_GETIMAGE, IMAGE_BITMAP, 0);
+ }
+
+ inline UINT CButton::GetButtonStyle() const
+ // returns the style of the button
+ {
+ assert(::IsWindow(m_hWnd));
+ return (UINT)GetWindowLongPtr(GWL_STYLE) & 0xff;
+ }
+
+ inline int CButton::GetCheck() const
+ // returns the check state of the button
+ {
+ assert(::IsWindow(m_hWnd));
+ return (int)SendMessage(BM_GETCHECK, 0, 0);
+ }
+
+ inline HCURSOR CButton::GetCursor() const
+ // returns the handle to the cursor associated withe the button
+ {
+ assert(::IsWindow(m_hWnd));
+ return (HCURSOR)::SendMessage(m_hWnd, BM_GETIMAGE, IMAGE_CURSOR, 0L);
+ }
+
+ inline HICON CButton::GetIcon() const
+ // returns the handle to the icon associated withe the button
+ {
+ assert(::IsWindow(m_hWnd));
+ return (HICON)SendMessage(BM_GETIMAGE, IMAGE_ICON, 0);
+ }
+
+ inline UINT CButton::GetState() const
+ // returns the state of the button
+ {
+ assert(::IsWindow(m_hWnd));
+ return (UINT)SendMessage(BM_GETSTATE, 0, 0);
+ }
+
+ inline HBITMAP CButton::SetBitmap(HBITMAP hBitmap) const
+ // sets the bitmap associated with the button
+ {
+ assert(::IsWindow(m_hWnd));
+ return (HBITMAP)SendMessage(BM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hBitmap);
+ }
+
+ inline void CButton::SetButtonStyle(DWORD dwStyle, BOOL bRedraw) const
+ // sets the button style
+ {
+ assert(::IsWindow(m_hWnd));
+ SendMessage(BM_SETSTYLE, dwStyle, bRedraw);
+ }
+
+ inline void CButton::SetCheck(int nCheckState) const
+ // sets the button check state
+ {
+ assert(::IsWindow(m_hWnd));
+ SendMessage(BM_SETCHECK, nCheckState, 0);
+ }
+
+ inline HCURSOR CButton::SetCursor(HCURSOR hCursor) const
+ // sets the cursor associated with the button
+ {
+ assert(::IsWindow(m_hWnd));
+ return (HCURSOR)SendMessage(STM_SETIMAGE, IMAGE_CURSOR, (LPARAM)hCursor);
+ }
+
+ inline HICON CButton::SetIcon(HICON hIcon) const
+ // sets the icon associated with the button
+ {
+ assert(::IsWindow(m_hWnd));
+ return (HICON)SendMessage( BM_SETIMAGE, IMAGE_ICON, (LPARAM)hIcon);
+ }
+
+ inline void CButton::SetState(BOOL bHighlight) const
+ // sets the button state
+ {
+ assert(::IsWindow(m_hWnd));
+ SendMessage(BM_SETSTATE, bHighlight, 0);
+ }
+
+ inline void CButton::PreCreate(CREATESTRUCT& cs)
+ {
+ cs.lpszClass = _T("Button");
+ }
+
+
+ ////////////////////////////////////////
+ // Definitions for the CEdit class
+ //
+ inline BOOL CEdit::CanUndo() const
+ // Returns TRUE if the edit control operation can be undone.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (BOOL)SendMessage(EM_CANUNDO, 0, 0);
+ }
+
+ inline int CEdit::CharFromPos(CPoint pt) const
+ // Returns the character index and line index of the character nearest the specified point.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (int)SendMessage(EM_CHARFROMPOS, 0, MAKELPARAM(pt.x, pt.y));
+ }
+
+ inline int CEdit::GetFirstVisibleLine() const
+ // Returns the zero-based index of the first visible character in a single-line edit control
+ // or the zero-based index of the uppermost visible line in a multiline edit control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (int)SendMessage(EM_GETFIRSTVISIBLELINE, 0, 0);
+ }
+
+ inline HLOCAL CEdit::GetHandle() const
+ // Returns a handle identifying the buffer containing the multiline edit control's text.
+ // It is not processed by single-line edit controls.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (HLOCAL)SendMessage(EM_GETHANDLE, 0, 0);
+ }
+
+ inline UINT CEdit::GetLimitText() const
+ // Returns the current text limit, in characters.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (UINT)SendMessage(EM_GETLIMITTEXT, 0, 0);
+ }
+
+ inline int CEdit::GetLine(int nIndex, LPTSTR lpszBuffer) const
+ // Copies characters to a buffer and returns the number of characters copied.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (int)::SendMessage(m_hWnd, EM_GETLINE, nIndex, (LPARAM)lpszBuffer);
+ }
+
+ inline int CEdit::GetLine(int nIndex, LPTSTR lpszBuffer, int nMaxLength) const
+ // Copies characters to a buffer and returns the number of characters copied.
+ {
+ assert(::IsWindow(m_hWnd));
+ *(LPWORD)lpszBuffer = (WORD)nMaxLength;
+ return (int)SendMessage(EM_GETLINE, nIndex, (LPARAM)lpszBuffer);
+ }
+
+ inline int CEdit::GetLineCount() const
+ // Returns the number of lines in the edit control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (int)SendMessage(EM_GETLINECOUNT, 0, 0);
+ }
+
+ inline DWORD CEdit::GetMargins() const
+ // Returns the widths of the left and right margins.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (DWORD)SendMessage(EM_GETMARGINS, 0, 0);
+ }
+
+ inline BOOL CEdit::GetModify() const
+ // Returns a flag indicating whether the content of an edit control has been modified.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (BOOL)SendMessage(EM_GETMODIFY, 0, 0);
+ }
+
+ inline TCHAR CEdit::GetPasswordChar() const
+ // Returns the character that edit controls use in conjunction with the ES_PASSWORD style.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (TCHAR)SendMessage(EM_GETPASSWORDCHAR, 0, 0);
+ }
+
+ inline void CEdit::GetRect(LPRECT lpRect) const
+ // Returns the coordinates of the formatting rectangle in an edit control.
+ {
+ assert(::IsWindow(m_hWnd));
+ SendMessage(EM_GETRECT, 0, (LPARAM)lpRect);
+ }
+
+ inline void CEdit::GetSel(int& nStartChar, int& nEndChar) const
+ // Returns the starting and ending character positions of the current selection in the edit control.
+ {
+ assert(::IsWindow(m_hWnd));
+ SendMessage(EM_GETSEL, (WPARAM)&nStartChar,(LPARAM)&nEndChar);
+ }
+
+ inline DWORD CEdit::GetSel() const
+ // Returns the starting and ending character positions of the current selection in the edit control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (DWORD)SendMessage(EM_GETSEL, 0, 0);
+ }
+
+ inline CPoint CEdit::PosFromChar(UINT nChar) const
+ // Returns the client coordinates of the specified character.
+ {
+ assert(::IsWindow(m_hWnd));
+ return CPoint( (DWORD)SendMessage(EM_POSFROMCHAR, nChar, 0));
+ }
+
+ inline void CEdit::SetHandle(HLOCAL hBuffer) const
+ // Sets a handle to the memory used as a text buffer, empties the undo buffer,
+ // resets the scroll positions to zero, and redraws the window.
+ {
+ assert(::IsWindow(m_hWnd));
+ SendMessage(EM_SETHANDLE, (WPARAM)hBuffer, 0);
+ }
+
+ inline void CEdit::SetLimitText(UINT nMax) const
+ // Sets the maximum number of characters the user may enter in the edit control.
+ {
+ assert(::IsWindow(m_hWnd));
+ SendMessage(EM_SETLIMITTEXT, (WPARAM)nMax, 0);
+ }
+
+ inline void CEdit::SetMargins(UINT nLeft, UINT nRight) const
+ // Sets the widths of the left and right margins, and redraws the edit control to reflect the new margins.
+ {
+ assert(::IsWindow(m_hWnd));
+ SendMessage(EM_SETMARGINS, EC_LEFTMARGIN|EC_RIGHTMARGIN, MAKELONG(nLeft, nRight));
+ }
+
+ inline void CEdit::SetModify(BOOL bModified) const
+ // Sets or clears the modification flag to indicate whether the edit control has been modified.
+ {
+ assert(::IsWindow(m_hWnd));
+ SendMessage(EM_SETMODIFY, bModified, 0);
+ }
+
+ inline void CEdit::EmptyUndoBuffer() const
+ // Empties the undo buffer and sets the undo flag retrieved by the EM_CANUNDO message to FALSE.
+ {
+ assert(::IsWindow(m_hWnd));
+ SendMessage(EM_EMPTYUNDOBUFFER, 0, 0);
+ }
+
+ inline BOOL CEdit::FmtLines(BOOL bAddEOL) const
+ // Adds or removes soft line-break characters (two carriage returns and a line feed) to the ends of wrapped lines
+ // in a multiline edit control. It is not processed by single-line edit controls.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (BOOL)SendMessage(EM_FMTLINES, bAddEOL, 0);
+ }
+
+ inline void CEdit::LimitText(int nChars) const
+ // Sets the text limit of an edit control. The text limit is the maximum amount of text, in TCHARs,
+ // that the user can type into the edit control.
+ {
+ assert(::IsWindow(m_hWnd));
+ SendMessage(EM_LIMITTEXT, nChars, 0);
+ }
+
+ inline int CEdit::LineFromChar(int nIndex) const
+ // Returns the zero-based number of the line in a multiline edit control that contains a specified character index.
+ // This message is the reverse of the EM_LINEINDEX message.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (int)SendMessage(EM_LINEFROMCHAR, (WPARAM)nIndex, 0);
+ }
+
+ inline int CEdit::LineIndex(int nLine) const
+ // Returns the character of a line in a multiline edit control.
+ // This message is the reverse of the EM_LINEFROMCHAR message
+ {
+ assert(::IsWindow(m_hWnd));
+ return (int)SendMessage(EM_LINEINDEX, (WPARAM)nLine, 0);
+ }
+
+ inline int CEdit::LineLength(int nLine) const
+ // Returns the length, in characters, of a single-line edit control. In a multiline edit control,
+ // returns the length, in characters, of a specified line.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (int)SendMessage(EM_LINELENGTH, (WPARAM)nLine, 0);
+ }
+
+ inline void CEdit::LineScroll(int nLines, int nChars) const
+ // Scrolls the text vertically in a single-line edit control or horizontally in a multiline edit control.
+ {
+ assert(::IsWindow(m_hWnd));
+ SendMessage(EM_LINESCROLL, (WPARAM)nChars, (LPARAM)nLines);
+ }
+
+ inline void CEdit::ReplaceSel(LPCTSTR lpszNewText, BOOL bCanUndo) const
+ // Replaces the current selection with the text in an application-supplied buffer, sends the parent window
+ // EN_UPDATE and EN_CHANGE messages, and updates the undo buffer.
+ {
+ assert(::IsWindow(m_hWnd));
+ SendMessage(EM_REPLACESEL, (WPARAM) bCanUndo, (LPARAM)lpszNewText);
+ }
+
+ inline void CEdit::SetPasswordChar(TCHAR ch) const
+ // Defines the character that edit controls use in conjunction with the ES_PASSWORD style.
+ {
+ assert(::IsWindow(m_hWnd));
+ SendMessage(EM_SETPASSWORDCHAR, ch, 0);
+ }
+
+ inline BOOL CEdit::SetReadOnly(BOOL bReadOnly) const
+ // Sets or removes the read-only style (ES_READONLY) in an edit control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (BOOL)SendMessage(EM_SETREADONLY, bReadOnly, 0);
+ }
+
+ inline void CEdit::SetRect(LPCRECT lpRect) const
+ // Sets the formatting rectangle for the multiline edit control and redraws the window.
+ {
+ assert(::IsWindow(m_hWnd));
+ SendMessage(EM_SETRECT, 0, (LPARAM)lpRect);
+ }
+
+ inline void CEdit::SetRectNP(LPCRECT lpRect) const
+ // Sets the formatting rectangle for the multiline edit control but does not redraw the window.
+ {
+ assert(::IsWindow(m_hWnd));
+ SendMessage(EM_SETRECTNP, 0, (LPARAM)lpRect);
+ }
+
+ inline void CEdit::SetSel(DWORD dwSelection, BOOL bNoScroll) const
+ // Selects a range of characters in the edit control by setting the starting and ending positions to be selected.
+ {
+ assert(::IsWindow(m_hWnd));
+ SendMessage(EM_SETSEL, LOWORD(dwSelection), HIWORD(dwSelection));
+ if (!bNoScroll)
+ SendMessage(EM_SCROLLCARET, 0, 0);
+ }
+
+ inline void CEdit::SetSel(int nStartChar, int nEndChar, BOOL bNoScroll) const
+ // Selects a range of characters in the edit control by setting the starting and ending positions to be selected.
+ {
+ assert(::IsWindow(m_hWnd));
+ SendMessage(m_hWnd, EM_SETSEL, nStartChar, nEndChar);
+ if (!bNoScroll)
+ SendMessage(EM_SCROLLCARET, 0, 0);
+ }
+
+ inline BOOL CEdit::SetTabStops(int nTabStops, LPINT rgTabStops) const
+ // Sets tab-stop positions in the multiline edit control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (BOOL)::SendMessage(m_hWnd, EM_SETTABSTOPS, nTabStops, (LPARAM)rgTabStops);
+ }
+
+ inline BOOL CEdit::SetTabStops() const
+ // Sets tab-stop positions in the multiline edit control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (BOOL)SendMessage( EM_SETTABSTOPS, 0, 0);
+ }
+
+ inline BOOL CEdit::SetTabStops(const int& cxEachStop) const
+ // Sets tab-stop positions in the multiline edit control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (BOOL)SendMessage(EM_SETTABSTOPS, 1, (LPARAM)(LPINT)&cxEachStop);
+ }
+
+ inline void CEdit::Clear() const
+ // Clears the current selection, if any, in an edit control.
+ {
+ assert(::IsWindow(m_hWnd));
+ SendMessage(WM_CLEAR, 0, 0);
+ }
+
+ inline void CEdit::Copy() const
+ // Copies text to the clipboard unless the style is ES_PASSWORD, in which case the message returns zero.
+ {
+ assert(::IsWindow(m_hWnd));
+ SendMessage(WM_COPY, 0, 0);
+ }
+
+ inline void CEdit::Cut() const
+ // Cuts the selection to the clipboard, or deletes the character to the left of the cursor if there is no selection.
+ {
+ assert(::IsWindow(m_hWnd));
+ SendMessage(WM_CUT, 0, 0);
+ }
+
+ inline void CEdit::Paste() const
+ // Pastes text from the clipboard into the edit control window at the caret position.
+ {
+ assert(::IsWindow(m_hWnd));
+ SendMessage(WM_PASTE, 0, 0);
+ }
+
+ inline void CEdit::Undo() const
+ // Removes any text that was just inserted or inserts any deleted characters and sets the selection to the inserted text.
+ {
+ assert(::IsWindow(m_hWnd));
+ SendMessage(EM_UNDO, 0, 0);
+ }
+
+ inline void CEdit::PreRegisterClass(WNDCLASS &wc)
+ {
+ // Set the Window Class
+ wc.lpszClassName = _T("Edit");
+ }
+
+
+ ////////////////////////////////////////
+ // Definitions for the CListbox class
+ //
+ inline int CListBox::GetCount() const
+ // Returns the number of items in the list box.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (int)SendMessage(LB_GETCOUNT, 0, 0);
+ }
+
+ inline int CListBox::GetHorizontalExtent() const
+ // Returns the scrollable width, in pixels, of a list box.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (int)SendMessage(LB_GETHORIZONTALEXTENT, 0, 0);
+ }
+
+ inline DWORD CListBox::GetItemData(int nIndex) const
+ // Returns the value associated with the specified item.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (DWORD)SendMessage(LB_GETITEMDATA, nIndex, 0);
+ }
+
+ inline void* CListBox::GetItemDataPtr(int nIndex) const
+ // Returns the value associated with the specified item.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (LPVOID)SendMessage(LB_GETITEMDATA, nIndex, 0);
+ }
+
+ inline int CListBox::GetItemHeight(int nIndex) const
+ // Returns the height, in pixels, of an item in a list box.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (int)SendMessage(LB_GETITEMHEIGHT, nIndex, 0L);
+ }
+
+ inline int CListBox::GetItemRect(int nIndex, LPRECT lpRect) const
+ // Retrieves the client coordinates of the specified list box item.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (int)SendMessage(LB_GETITEMRECT, nIndex, (LPARAM)lpRect);
+ }
+
+ inline LCID CListBox::GetLocale() const
+ // Retrieves the locale of the list box. The high-order word contains the country/region code
+ // and the low-order word contains the language identifier.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (LCID)::SendMessage(m_hWnd, LB_GETLOCALE, 0, 0);
+ }
+
+ inline int CListBox::GetSel(int nIndex) const
+ // Returns the selection state of a list box item.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (int)SendMessage(LB_GETSEL, nIndex, 0);
+ }
+
+ inline int CListBox::GetText(int nIndex, LPTSTR lpszBuffer) const
+ // Retrieves the string associated with a specified item and the length of the string.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (int)::SendMessage(m_hWnd, LB_GETTEXT, nIndex, (LPARAM)lpszBuffer);
+ }
+
+ inline int CListBox::GetTextLen(int nIndex) const
+ // Returns the length, in characters, of the string associated with a specified item.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (int)SendMessage( LB_GETTEXTLEN, nIndex, 0);
+ }
+
+ inline int CListBox::GetTopIndex() const
+ // Returns the index of the first visible item in a list box.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (int)SendMessage(LB_GETTOPINDEX, 0, 0);
+ }
+
+ inline UINT CListBox::ItemFromPoint(CPoint pt, BOOL& bOutside) const
+ // Retrieves the zero-based index of the item nearest the specified point in a list box.
+ {
+ assert(::IsWindow(m_hWnd));
+ DWORD dw = (DWORD)::SendMessage(m_hWnd, LB_ITEMFROMPOINT, 0, MAKELPARAM(pt.x, pt.y));
+ bOutside = !!HIWORD(dw);
+ return LOWORD(dw);
+ }
+
+ inline void CListBox::SetColumnWidth(int cxWidth) const
+ // Sets the width, in pixels, of all columns in a list box.
+ {
+ assert(::IsWindow(m_hWnd));
+ SendMessage(LB_SETCOLUMNWIDTH, cxWidth, 0);
+ }
+
+ inline void CListBox::SetHorizontalExtent(int cxExtent) const
+ // Sets the scrollable width, in pixels, of a list box.
+ {
+ assert(::IsWindow(m_hWnd));
+ SendMessage(LB_SETHORIZONTALEXTENT, cxExtent, 0);
+ }
+
+ inline int CListBox::SetItemData(int nIndex, DWORD dwItemData) const
+ // Associates a value with a list box item.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (int)SendMessage(LB_SETITEMDATA, nIndex, (LPARAM)dwItemData);
+ }
+
+ inline int CListBox::SetItemDataPtr(int nIndex, void* pData) const
+ // Associates a value with a list box item.
+ {
+ assert(::IsWindow(m_hWnd));
+ return SetItemData(nIndex, (DWORD)(DWORD_PTR)pData);
+ }
+
+ inline int CListBox::SetItemHeight(int nIndex, UINT cyItemHeight) const
+ // Sets the height, in pixels, of an item or items in a list box.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (int)SendMessage(LB_SETITEMHEIGHT, nIndex, MAKELONG(cyItemHeight, 0));
+ }
+
+ inline LCID CListBox::SetLocale(LCID nNewLocale) const
+ // Sets the locale of a list box and returns the previous locale identifier.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (LCID)::SendMessage(m_hWnd, LB_SETLOCALE, (WPARAM)nNewLocale, 0);
+ }
+
+ inline BOOL CListBox::SetTabStops(int nTabStops, LPINT rgTabStops) const
+ // Sets the tab stops to those specified in a specified array.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (BOOL)SendMessage(LB_SETTABSTOPS, nTabStops, (LPARAM)rgTabStops);
+ }
+
+ inline void CListBox::SetTabStops() const
+ // Sets the tab stops to those specified in a specified array.
+ {
+ assert(::IsWindow(m_hWnd));
+ SendMessage(LB_SETTABSTOPS, 0, 0);
+ }
+
+ inline BOOL CListBox::SetTabStops(const int& cxEachStop) const
+ // Sets the tab stops to those specified in a specified array.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (BOOL)SendMessage(LB_SETTABSTOPS, 1, (LPARAM)(LPINT)&cxEachStop);
+ }
+
+ inline int CListBox::SetTopIndex(int nIndex) const
+ // Scrolls the list box so the specified item is at the top of the visible range.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (int)SendMessage(LB_SETTOPINDEX, nIndex, 0);
+ }
+
+ inline int CListBox::GetCurSel() const
+ // Returns the index of the currently selected item.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (int)SendMessage(LB_GETCURSEL, 0, 0);
+ }
+
+ inline int CListBox::SetCurSel(int nSelect) const
+ // Selects a specified list box item.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (int)SendMessage(LB_SETCURSEL, nSelect, 0);
+ }
+
+ inline int CListBox::GetAnchorIndex() const
+ // Returns the index of the item that the mouse last selected.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (int)SendMessage(LB_GETANCHORINDEX, 0, 0);
+ }
+
+ inline int CListBox::GetCaretIndex() const
+ // Returns the index of the item that has the focus rectangle.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (int)SendMessage(LB_GETCARETINDEX, 0, 0L);
+ }
+
+ inline int CListBox::GetSelCount() const
+ // Returns the number of selected items in a multiple-selection list box.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (int)SendMessage(LB_GETSELCOUNT, 0, 0);
+ }
+
+ inline int CListBox::GetSelItems(int nMaxItems, LPINT rgIndex) const
+ // Creates an array of the indexes of all selected items in a multiple-selection list box
+ // and returns the total number of selected items.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (int)SendMessage(LB_GETSELITEMS, nMaxItems, (LPARAM)rgIndex);
+ }
+
+ inline int CListBox::SelItemRange(BOOL bSelect, int nFirstItem, int nLastItem) const
+ // Selects a specified range of items in a list box.
+ {
+ assert(::IsWindow(m_hWnd));
+ if (bSelect)
+ return (int)SendMessage(LB_SELITEMRANGEEX, nFirstItem, nLastItem);
+ else
+ return (int)SendMessage(LB_SELITEMRANGEEX, nLastItem, nFirstItem);
+ }
+
+ inline void CListBox::SetAnchorIndex(int nIndex) const
+ // Sets the item that the mouse last selected to a specified item.
+ {
+ assert(::IsWindow(m_hWnd));
+ SendMessage(LB_SETANCHORINDEX, nIndex, 0);
+ }
+
+ inline int CListBox::SetCaretIndex(int nIndex, BOOL bScroll) const
+ // Sets the focus rectangle to a specified list box item.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (int)SendMessage(LB_SETCARETINDEX, nIndex, MAKELONG(bScroll, 0));
+ }
+
+ inline int CListBox::SetSel(int nIndex, BOOL bSelect) const
+ // Selects an item in a multiple-selection list box.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (int)SendMessage(LB_SETSEL, bSelect, nIndex);
+ }
+
+ inline int CListBox::AddString(LPCTSTR lpszItem) const
+ // Adds a string to a list box and returns its index.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (int)SendMessage(LB_ADDSTRING, 0, (LPARAM)lpszItem);
+ }
+
+ inline int CListBox::DeleteString(UINT nIndex) const
+ // Removes a string from a list box and returns the number of strings remaining in the list.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (int)SendMessage(LB_DELETESTRING, nIndex, 0);
+ }
+
+ inline int CListBox::Dir(UINT attr, LPCTSTR lpszWildCard) const
+ // Adds a list of filenames to a list box and returns the index of the last filename added.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (int)SendMessage(LB_DIR, attr, (LPARAM)lpszWildCard);
+ }
+
+ inline int CListBox::FindString(int nStartAfter, LPCTSTR lpszItem) const
+ // Returns the index of the first string in the list box that begins with a specified string.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (int)SendMessage(LB_FINDSTRING, nStartAfter, (LPARAM)lpszItem);
+ }
+
+ inline int CListBox::FindStringExact(int nIndexStart, LPCTSTR lpszFind) const
+ // Returns the index of the string in the list box that is equal to a specified string.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (int)SendMessage(LB_FINDSTRINGEXACT, nIndexStart, (LPARAM)lpszFind);
+ }
+
+ inline int CListBox::InsertString(int nIndex, LPCTSTR lpszItem) const
+ // Inserts a string at a specified index in a list box.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (int)SendMessage(LB_INSERTSTRING, nIndex, (LPARAM)lpszItem);
+ }
+
+ inline void CListBox::ResetContent() const
+ // Removes all items from a list box.
+ {
+ assert(::IsWindow(m_hWnd));
+ SendMessage(LB_RESETCONTENT, 0, 0);
+ }
+
+ inline int CListBox::SelectString(int nStartAfter, LPCTSTR lpszItem) const
+ // Selects the first string it finds that matches a specified prefix.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (int)::SendMessage(m_hWnd, LB_SELECTSTRING, nStartAfter, (LPARAM)lpszItem);
+ }
+
+ inline void CListBox::PreRegisterClass(WNDCLASS &wc)
+ {
+ // Set the Window Class
+ wc.lpszClassName = _T("ListBox");
+ }
+
+
+ ////////////////////////////////////////
+ // Definitions for the CStatic class
+ //
+ inline HBITMAP CStatic::GetBitmap() const
+ // Returns the handle to the bitmap for the static control
+ {
+ assert(::IsWindow(m_hWnd));
+ return (HBITMAP)SendMessage(STM_GETIMAGE, IMAGE_BITMAP, 0);
+ }
+
+ inline HCURSOR CStatic::GetCursor() const
+ // Returns the handle to the icon for the static control
+ {
+ assert(::IsWindow(m_hWnd));
+ return (HCURSOR)SendMessage(STM_GETIMAGE, IMAGE_CURSOR, 0);
+ }
+
+ inline HENHMETAFILE CStatic::GetEnhMetaFile() const
+ // Returns the handle to the enhanced metafile for the static control
+ {
+ assert(::IsWindow(m_hWnd));
+ return (HENHMETAFILE)SendMessage(STM_GETIMAGE, IMAGE_ENHMETAFILE, 0);
+ }
+
+ inline HICON CStatic::GetIcon() const
+ // Returns the handle to the icon for the static control
+ {
+ assert(::IsWindow(m_hWnd));
+ return (HICON)SendMessage(STM_GETIMAGE, IMAGE_ICON, 0);
+ }
+
+ inline HBITMAP CStatic::SetBitmap(HBITMAP hBitmap) const
+ // Sets the handle to the bitmap for the static control
+ {
+ assert(::IsWindow(m_hWnd));
+ return (HBITMAP)SendMessage(STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hBitmap);
+ }
+
+ inline HCURSOR CStatic::SetCursor(HCURSOR hCursor) const
+ // Sets the handle to the cursor for the static control
+ {
+ assert(::IsWindow(m_hWnd));
+ return (HCURSOR)SendMessage(STM_SETIMAGE, IMAGE_CURSOR, (LPARAM)hCursor);
+ }
+
+ inline HENHMETAFILE CStatic::SetEnhMetaFile(HENHMETAFILE hMetaFile) const
+ // Sets the handle to the enhanced metafile for the static control
+ {
+ assert(::IsWindow(m_hWnd));
+ return (HENHMETAFILE)SendMessage(STM_SETIMAGE, IMAGE_ENHMETAFILE, (LPARAM)hMetaFile);
+ }
+
+ inline HICON CStatic::SetIcon(HICON hIcon) const
+ // Sets the handle to the icon for the static control
+ {
+ assert(::IsWindow(m_hWnd));
+ return (HICON)SendMessage(STM_SETIMAGE, IMAGE_ICON, (LPARAM)hIcon);
+ }
+
+ inline void CStatic::PreRegisterClass(WNDCLASS &wc)
+ {
+ // Set the Window Class
+ wc.lpszClassName = _T("Static");
+ }
+
+}
+
+#endif // _WIN32XX_STDCONTROLS_H_
+
diff --git a/mmc_updater/depends/win32cpp/tab.h b/mmc_updater/depends/win32cpp/tab.h
new file mode 100644
index 00000000..15699144
--- /dev/null
+++ b/mmc_updater/depends/win32cpp/tab.h
@@ -0,0 +1,1658 @@
+// Win32++ Version 7.2
+// Released: 5th AUgust 2011
+//
+// David Nash
+// email: dnash@bigpond.net.au
+// url: https://sourceforge.net/projects/win32-framework
+//
+//
+// Copyright (c) 2005-2011 David Nash
+//
+// Permission is hereby granted, free of charge, to
+// any person obtaining a copy of this software and
+// associated documentation files (the "Software"),
+// to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify,
+// merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom
+// the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice
+// shall be included in all copies or substantial portions
+// of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
+// OR OTHER DEALINGS IN THE SOFTWARE.
+//
+////////////////////////////////////////////////////////
+
+
+///////////////////////////////////////////////////////
+// tab.h
+// Declaration of the CTab and CMDITab classes
+
+#ifndef _WIN32XX_TAB_H_
+#define _WIN32XX_TAB_H_
+
+#include "wincore.h"
+#include "dialog.h"
+#include "gdi.h"
+#include "default_resource.h"
+
+namespace Win32xx
+{
+
+ struct TabPageInfo
+ {
+ TCHAR szTabText[MAX_MENU_STRING];
+ int iImage; // index of this tab's image
+ int idTab; // identifier for this tab (optional)
+ CWnd* pView; // pointer to the view window
+ };
+
+ class CTab : public CWnd
+ {
+ protected:
+ // Declaration of the CSelectDialog class, a nested class of CTab
+ // It creates the dialog to choose which tab to activate
+ class CSelectDialog : public CDialog
+ {
+ public:
+ CSelectDialog(LPCDLGTEMPLATE lpTemplate, CWnd* pParent = NULL);
+ virtual ~CSelectDialog() {}
+ virtual void AddItem(LPCTSTR szString);
+ virtual BOOL IsTab() const { return FALSE; }
+
+ protected:
+ virtual BOOL OnInitDialog();
+ virtual void OnOK();
+ virtual void OnCancel() { EndDialog(-2); }
+
+ private:
+ CSelectDialog(const CSelectDialog&); // Disable copy construction
+ CSelectDialog& operator = (const CSelectDialog&); // Disable assignment operator
+
+ std::vector<tString> m_vItems;
+ int IDC_LIST;
+
+ };
+ public:
+ CTab();
+ virtual ~CTab();
+ virtual int AddTabPage(WndPtr pView, LPCTSTR szTabText, HICON hIcon, UINT idTab);
+ virtual int AddTabPage(WndPtr pView, LPCTSTR szTabText, int nID_Icon, UINT idTab = 0);
+ virtual int AddTabPage(WndPtr pView, LPCTSTR szTabText);
+ virtual CRect GetCloseRect() const;
+ virtual CRect GetListRect() const;
+ virtual HMENU GetListMenu();
+ virtual BOOL GetTabsAtTop() const;
+ virtual int GetTabIndex(CWnd* pWnd) const;
+ virtual TabPageInfo GetTabPageInfo(UINT nTab) const;
+ virtual int GetTextHeight() const;
+ virtual void RecalcLayout();
+ virtual void RemoveTabPage(int nPage);
+ virtual void SelectPage(int nPage);
+ virtual void SetFixedWidth(BOOL bEnabled);
+ virtual void SetOwnerDraw(BOOL bEnabled);
+ virtual void SetShowButtons(BOOL bShow);
+ virtual void SetTabIcon(int i, HICON hIcon);
+ virtual void SetTabsAtTop(BOOL bTop);
+ virtual void SetTabText(UINT nTab, LPCTSTR szText);
+ virtual void SwapTabs(UINT nTab1, UINT nTab2);
+
+ // Attributes
+ std::vector <TabPageInfo>& GetAllTabs() const { return (std::vector <TabPageInfo>&) m_vTabPageInfo; }
+ HIMAGELIST GetImageList() const { return m_himlTab; }
+ BOOL GetShowButtons() const { return m_bShowButtons; }
+ int GetTabHeight() const { return m_nTabHeight; }
+ CWnd* GetActiveView() const { return m_pActiveView; }
+ void SetTabHeight(int nTabHeight) { m_nTabHeight = nTabHeight; NotifyChanged();}
+
+ // Wrappers for Win32 Macros
+ void AdjustRect(BOOL fLarger, RECT *prc) const;
+ int GetCurFocus() const;
+ int GetCurSel() const;
+ BOOL GetItem(int iItem, LPTCITEM pitem) const;
+ int GetItemCount() const;
+ int HitTest(TCHITTESTINFO& info) const;
+ void SetCurFocus(int iItem) const;
+ int SetCurSel(int iItem) const;
+ DWORD SetItemSize(int cx, int cy) const;
+ int SetMinTabWidth(int cx) const;
+ void SetPadding(int cx, int cy) const;
+
+ protected:
+ virtual void DrawCloseButton(CDC& DrawDC);
+ virtual void DrawListButton(CDC& DrawDC);
+ virtual void DrawTabs(CDC& dcMem);
+ virtual void DrawTabBorders(CDC& dcMem, CRect& rcTab);
+ virtual void OnCreate();
+ virtual void OnLButtonDown(WPARAM wParam, LPARAM lParam);
+ virtual void OnLButtonUp(WPARAM wParam, LPARAM lParam);
+ virtual void OnMouseLeave(WPARAM wParam, LPARAM lParam);
+ virtual void OnMouseMove(WPARAM wParam, LPARAM lParam);
+ virtual LRESULT OnNCHitTest(WPARAM wParam, LPARAM lParam);
+ virtual LRESULT OnNotifyReflect(WPARAM wParam, LPARAM lParam);
+ virtual void NotifyChanged();
+ virtual void Paint();
+ virtual void PreCreate(CREATESTRUCT& cs);
+ virtual void PreRegisterClass(WNDCLASS &wc);
+ virtual void SetTabSize();
+ virtual void ShowListDialog();
+ virtual void ShowListMenu();
+ virtual LRESULT WndProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam);
+
+ private:
+ CTab(const CTab&); // Disable copy construction
+ CTab& operator = (const CTab&); // Disable assignment operator
+
+ SIZE GetMaxTabSize() const;
+ void ShowActiveView(CWnd* pView);
+
+ std::vector<TabPageInfo> m_vTabPageInfo;
+ std::vector<WndPtr> m_vTabViews;
+ CFont m_Font;
+ HIMAGELIST m_himlTab;
+ HMENU m_hListMenu;
+ CWnd* m_pActiveView;
+ BOOL m_bShowButtons; // Show or hide the close and list button
+ BOOL m_IsTracking;
+ BOOL m_IsClosePressed;
+ BOOL m_IsListPressed;
+ BOOL m_IsListMenuActive;
+ int m_nTabHeight;
+ };
+
+ ////////////////////////////////////////
+ // Declaration of the CTabbedMDI class
+ class CTabbedMDI : public CWnd
+ {
+ public:
+ CTabbedMDI();
+ virtual ~CTabbedMDI();
+ virtual CWnd* AddMDIChild(CWnd* pView, LPCTSTR szTabText, int idMDIChild = 0);
+ virtual void CloseActiveMDI();
+ virtual void CloseAllMDIChildren();
+ virtual void CloseMDIChild(int nTab);
+ virtual CWnd* GetActiveMDIChild() const;
+ virtual int GetActiveMDITab() const;
+ virtual CWnd* GetMDIChild(int nTab) const;
+ virtual int GetMDIChildCount() const;
+ virtual int GetMDIChildID(int nTab) const;
+ virtual LPCTSTR GetMDIChildTitle(int nTab) const;
+ virtual HMENU GetListMenu() const { return GetTab().GetListMenu(); }
+ virtual CTab& GetTab() const {return (CTab&)m_Tab;}
+ virtual BOOL LoadRegistrySettings(tString tsRegistryKeyName);
+ virtual void RecalcLayout();
+ virtual BOOL SaveRegistrySettings(tString tsRegistryKeyName);
+ virtual void SetActiveMDIChild(CWnd* pWnd);
+ virtual void SetActiveMDITab(int nTab);
+
+ protected:
+ virtual HWND Create(CWnd* pParent);
+ virtual CWnd* NewMDIChildFromID(int idMDIChild);
+ virtual void OnCreate();
+ virtual void OnDestroy(WPARAM wParam, LPARAM lParam);
+ virtual LRESULT OnNotify(WPARAM wParam, LPARAM lParam);
+ virtual void OnWindowPosChanged(WPARAM wParam, LPARAM lParam);
+ virtual LRESULT WndProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam);
+
+ private:
+ CTabbedMDI(const CTabbedMDI&); // Disable copy construction
+ CTabbedMDI& operator = (const CTabbedMDI&); // Disable assignment operator
+
+ CTab m_Tab;
+ };
+
+}
+
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+namespace Win32xx
+{
+
+ /////////////////////////////////////////////////////////////
+ // Definitions for the CSelectDialog class nested within CTab
+ //
+ inline CTab::CSelectDialog::CSelectDialog(LPCDLGTEMPLATE lpTemplate, CWnd* pParent) :
+ CDialog(lpTemplate, pParent), IDC_LIST(121)
+ {
+ }
+
+ inline BOOL CTab::CSelectDialog::OnInitDialog()
+ {
+ for (UINT u = 0; u < m_vItems.size(); ++u)
+ {
+ SendDlgItemMessage(IDC_LIST, LB_ADDSTRING, 0, (LPARAM) m_vItems[u].c_str());
+ }
+
+ return true;
+ }
+
+ inline void CTab::CSelectDialog::AddItem(LPCTSTR szString)
+ {
+ m_vItems.push_back(szString);
+ }
+
+ inline void CTab::CSelectDialog::OnOK()
+ {
+ int iSelect = (int)SendDlgItemMessage(IDC_LIST, LB_GETCURSEL, 0, 0);
+ if (iSelect != LB_ERR)
+ EndDialog(iSelect);
+ else
+ EndDialog(-2);
+ }
+
+
+ //////////////////////////////////////////////////////////
+ // Definitions for the CTab class
+ //
+ inline CTab::CTab() : m_hListMenu(NULL), m_pActiveView(NULL), m_bShowButtons(FALSE), m_IsTracking(FALSE), m_IsClosePressed(FALSE),
+ m_IsListPressed(FALSE), m_IsListMenuActive(FALSE), m_nTabHeight(0)
+ {
+ // Create and assign the image list
+ m_himlTab = ImageList_Create(16, 16, ILC_MASK|ILC_COLOR32, 0, 0);
+
+ // Set the tab control's font
+ NONCLIENTMETRICS info = {0};
+ info.cbSize = GetSizeofNonClientMetrics();
+ SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(info), &info, 0);
+ m_Font.CreateFontIndirect(&info.lfStatusFont);
+ }
+
+ inline CTab::~CTab()
+ {
+ ImageList_Destroy(m_himlTab);
+
+ if (IsMenu(m_hListMenu)) ::DestroyMenu(m_hListMenu);
+ }
+
+ inline int CTab::AddTabPage(WndPtr pView, LPCTSTR szTabText, HICON hIcon, UINT idTab)
+ {
+ assert(pView.get());
+ assert(lstrlen(szTabText) < MAX_MENU_STRING);
+
+ m_vTabViews.push_back(pView);
+
+ TabPageInfo tpi = {0};
+ tpi.pView = pView.get();
+ tpi.idTab = idTab;
+ lstrcpyn(tpi.szTabText, szTabText, MAX_MENU_STRING);
+ if (hIcon)
+ tpi.iImage = ImageList_AddIcon(GetImageList(), hIcon);
+ else
+ tpi.iImage = -1;
+
+ int iNewPage = (int)m_vTabPageInfo.size();
+ m_vTabPageInfo.push_back(tpi);
+
+ if (m_hWnd)
+ {
+ TCITEM tie = {0};
+ tie.mask = TCIF_TEXT | TCIF_IMAGE;
+ tie.iImage = tpi.iImage;
+ tie.pszText = tpi.szTabText;
+ TabCtrl_InsertItem(m_hWnd, iNewPage, &tie);
+
+ SetTabSize();
+ SelectPage(iNewPage);
+ NotifyChanged();
+ }
+
+ return iNewPage;
+ }
+
+ inline int CTab::AddTabPage(WndPtr pView, LPCTSTR szTabText, int idIcon, UINT idTab /* = 0*/)
+ {
+ HICON hIcon = (HICON)LoadImage(GetApp()->GetResourceHandle(), MAKEINTRESOURCE(idIcon), IMAGE_ICON, 0, 0, LR_SHARED);
+ return AddTabPage(pView, szTabText, hIcon, idTab);
+ }
+
+ inline int CTab::AddTabPage(WndPtr pView, LPCTSTR szTabText)
+ {
+ return AddTabPage(pView, szTabText, (HICON)0, 0);
+ }
+
+ inline void CTab::DrawCloseButton(CDC& DrawDC)
+ {
+ // The close button isn't displayed on Win95
+ if (GetWinVersion() == 1400) return;
+
+ if (!m_bShowButtons) return;
+ if (!GetActiveView()) return;
+ if (!(GetWindowLongPtr(GWL_STYLE) & TCS_FIXEDWIDTH)) return;
+ if (!(GetWindowLongPtr(GWL_STYLE) & TCS_OWNERDRAWFIXED)) return;
+
+ // Determine the close button's drawing position relative to the window
+ CRect rcClose = GetCloseRect();
+
+ CPoint pt = GetCursorPos();
+ ScreenToClient(pt);
+ UINT uState = rcClose.PtInRect(pt)? m_IsClosePressed? 2: 1: 0;
+
+ // Draw the outer highlight for the close button
+ if (!IsRectEmpty(&rcClose))
+ {
+ switch (uState)
+ {
+ case 0:
+ {
+ DrawDC.CreatePen(PS_SOLID, 1, RGB(232, 228, 220));
+
+ DrawDC.MoveTo(rcClose.left, rcClose.bottom);
+ DrawDC.LineTo(rcClose.right, rcClose.bottom);
+ DrawDC.LineTo(rcClose.right, rcClose.top);
+ DrawDC.LineTo(rcClose.left, rcClose.top);
+ DrawDC.LineTo(rcClose.left, rcClose.bottom);
+ break;
+ }
+
+ case 1:
+ {
+ // Draw outline, white at top, black on bottom
+ DrawDC.CreatePen(PS_SOLID, 1, RGB(0, 0, 0));
+ DrawDC.MoveTo(rcClose.left, rcClose.bottom);
+ DrawDC.LineTo(rcClose.right, rcClose.bottom);
+ DrawDC.LineTo(rcClose.right, rcClose.top);
+ DrawDC.CreatePen(PS_SOLID, 1, RGB(255, 255, 255));
+ DrawDC.LineTo(rcClose.left, rcClose.top);
+ DrawDC.LineTo(rcClose.left, rcClose.bottom);
+ }
+
+ break;
+ case 2:
+ {
+ // Draw outline, black on top, white on bottom
+ DrawDC.CreatePen(PS_SOLID, 1, RGB(255, 255, 255));
+ DrawDC.MoveTo(rcClose.left, rcClose.bottom);
+ DrawDC.LineTo(rcClose.right, rcClose.bottom);
+ DrawDC.LineTo(rcClose.right, rcClose.top);
+ DrawDC.CreatePen(PS_SOLID, 1, RGB(0, 0, 0));
+ DrawDC.LineTo(rcClose.left, rcClose.top);
+ DrawDC.LineTo(rcClose.left, rcClose.bottom);
+ }
+ break;
+ }
+
+ // Manually draw close button
+ DrawDC.CreatePen(PS_SOLID, 1, RGB(64, 64, 64));
+
+ DrawDC.MoveTo(rcClose.left + 3, rcClose.top +3);
+ DrawDC.LineTo(rcClose.right - 2, rcClose.bottom -2);
+
+ DrawDC.MoveTo(rcClose.left + 4, rcClose.top +3);
+ DrawDC.LineTo(rcClose.right - 2, rcClose.bottom -3);
+
+ DrawDC.MoveTo(rcClose.left + 3, rcClose.top +4);
+ DrawDC.LineTo(rcClose.right - 3, rcClose.bottom -2);
+
+ DrawDC.MoveTo(rcClose.right -3, rcClose.top +3);
+ DrawDC.LineTo(rcClose.left + 2, rcClose.bottom -2);
+
+ DrawDC.MoveTo(rcClose.right -3, rcClose.top +4);
+ DrawDC.LineTo(rcClose.left + 3, rcClose.bottom -2);
+
+ DrawDC.MoveTo(rcClose.right -4, rcClose.top +3);
+ DrawDC.LineTo(rcClose.left + 2, rcClose.bottom -3);
+ }
+ }
+
+ inline void CTab::DrawListButton(CDC& DrawDC)
+ {
+ // The list button isn't displayed on Win95
+ if (GetWinVersion() == 1400) return;
+
+ if (!m_bShowButtons) return;
+ if (!GetActiveView()) return;
+ if (!(GetWindowLongPtr(GWL_STYLE) & TCS_FIXEDWIDTH)) return;
+ if (!(GetWindowLongPtr(GWL_STYLE) & TCS_OWNERDRAWFIXED)) return;
+
+ // Determine the list button's drawing position relative to the window
+ CRect rcList = GetListRect();
+
+ CPoint pt = GetCursorPos();
+ ScreenToClient(pt);
+ UINT uState = rcList.PtInRect(pt)? 1: 0;
+ if (m_IsListMenuActive) uState = 2;
+
+ // Draw the outer highlight for the list button
+ if (!IsRectEmpty(&rcList))
+ {
+ switch (uState)
+ {
+ case 0:
+ {
+ DrawDC.CreatePen(PS_SOLID, 1, RGB(232, 228, 220));
+
+ DrawDC.MoveTo(rcList.left, rcList.bottom);
+ DrawDC.LineTo(rcList.right, rcList.bottom);
+ DrawDC.LineTo(rcList.right, rcList.top);
+ DrawDC.LineTo(rcList.left, rcList.top);
+ DrawDC.LineTo(rcList.left, rcList.bottom);
+ break;
+ }
+
+ case 1:
+ {
+ // Draw outline, white at top, black on bottom
+ DrawDC.CreatePen(PS_SOLID, 1, RGB(0, 0, 0));
+ DrawDC.MoveTo(rcList.left, rcList.bottom);
+ DrawDC.LineTo(rcList.right, rcList.bottom);
+ DrawDC.LineTo(rcList.right, rcList.top);
+ DrawDC.CreatePen(PS_SOLID, 1, RGB(255, 255, 255));
+ DrawDC.LineTo(rcList.left, rcList.top);
+ DrawDC.LineTo(rcList.left, rcList.bottom);
+ }
+
+ break;
+ case 2:
+ {
+ // Draw outline, black on top, white on bottom
+ DrawDC.CreatePen(PS_SOLID, 1, RGB(255, 255, 255));
+ DrawDC.MoveTo(rcList.left, rcList.bottom);
+ DrawDC.LineTo(rcList.right, rcList.bottom);
+ DrawDC.LineTo(rcList.right, rcList.top);
+ DrawDC.CreatePen(PS_SOLID, 1, RGB(0, 0, 0));
+ DrawDC.LineTo(rcList.left, rcList.top);
+ DrawDC.LineTo(rcList.left, rcList.bottom);
+ }
+ break;
+ }
+
+ // Manually draw list button
+ DrawDC.CreatePen(PS_SOLID, 1, RGB(64, 64, 64));
+
+ int MaxLength = (int)(0.65 * rcList.Width());
+ int topGap = 1 + rcList.Height()/3;
+ for (int i = 0; i <= MaxLength/2; i++)
+ {
+ int Length = MaxLength - 2*i;
+ DrawDC.MoveTo(rcList.left +1 + (rcList.Width() - Length)/2, rcList.top +topGap +i);
+ DrawDC.LineTo(rcList.left +1 + (rcList.Width() - Length)/2 + Length, rcList.top +topGap +i);
+ }
+ }
+ }
+
+ inline void CTab::DrawTabs(CDC& dcMem)
+ {
+ // Draw the tab buttons:
+ for (int i = 0; i < TabCtrl_GetItemCount(m_hWnd); ++i)
+ {
+ CRect rcItem;
+ TabCtrl_GetItemRect(m_hWnd, i, &rcItem);
+ if (!rcItem.IsRectEmpty())
+ {
+ if (i == TabCtrl_GetCurSel(m_hWnd))
+ {
+ dcMem.CreateSolidBrush(RGB(248,248,248));
+ dcMem.SetBkColor(RGB(248,248,248));
+ }
+ else
+ {
+ dcMem.CreateSolidBrush(RGB(200,200,200));
+ dcMem.SetBkColor(RGB(200,200,200));
+ }
+
+ dcMem.CreatePen(PS_SOLID, 1, RGB(160, 160, 160));
+ dcMem.RoundRect(rcItem.left+1, rcItem.top, rcItem.right+2, rcItem.bottom, 6, 6);
+
+ if (rcItem.Width() >= 24)
+ {
+ TCHAR szText[30];
+ TCITEM tcItem = {0};
+ tcItem.mask = TCIF_TEXT | TCIF_IMAGE;
+ tcItem.cchTextMax = 30;
+ tcItem.pszText = szText;
+ TabCtrl_GetItem(m_hWnd, i, &tcItem);
+ int xImage;
+ int yImage;
+ int yOffset = 0;
+ if (ImageList_GetIconSize(m_himlTab, &xImage, &yImage))
+ yOffset = (rcItem.Height() - yImage)/2;
+
+ // Draw the icon
+ ImageList_Draw(m_himlTab, tcItem.iImage, dcMem, rcItem.left+5, rcItem.top+yOffset, ILD_NORMAL);
+
+ // Draw the text
+ dcMem.SelectObject(&m_Font);
+
+ // Calculate the size of the text
+ CRect rcText = rcItem;
+
+ int iImageSize = 20;
+ int iPadding = 4;
+ if (tcItem.iImage >= 0)
+ rcText.left += iImageSize;
+
+ rcText.left += iPadding;
+ dcMem.DrawText(szText, -1, rcText, DT_LEFT|DT_VCENTER|DT_SINGLELINE|DT_END_ELLIPSIS);
+ }
+ }
+ }
+ }
+
+ inline void CTab::DrawTabBorders(CDC& dcMem, CRect& rcTab)
+ {
+ BOOL IsBottomTab = (BOOL)GetWindowLongPtr(GWL_STYLE) & TCS_BOTTOM;
+
+ // Draw a lighter rectangle touching the tab buttons
+ CRect rcItem;
+ TabCtrl_GetItemRect(m_hWnd, 0, &rcItem);
+ int left = rcItem.left +1;
+ int right = rcTab.right;
+ int top = rcTab.bottom;
+ int bottom = top + 3;
+
+ if (!IsBottomTab)
+ {
+ bottom = MAX(rcTab.top, m_nTabHeight +4);
+ top = bottom -3;
+ }
+
+ dcMem.CreateSolidBrush(RGB(248,248,248));
+ dcMem.CreatePen(PS_SOLID, 1, RGB(248,248,248));
+ if (!rcItem.IsRectEmpty())
+ {
+ dcMem.Rectangle(left, top, right, bottom);
+
+ // Draw a darker line below the rectangle
+ dcMem.CreatePen(PS_SOLID, 1, RGB(160, 160, 160));
+ if (IsBottomTab)
+ {
+ dcMem.MoveTo(left-1, bottom);
+ dcMem.LineTo(right, bottom);
+ }
+ else
+ {
+ dcMem.MoveTo(left-1, top-1);
+ dcMem.LineTo(right, top-1);
+ }
+
+ // Draw a lighter line over the darker line for the selected tab
+ dcMem.CreatePen(PS_SOLID, 1, RGB(248,248,248));
+ TabCtrl_GetItemRect(m_hWnd, TabCtrl_GetCurSel(m_hWnd), &rcItem);
+ OffsetRect(&rcItem, 1, 1);
+
+ if (IsBottomTab)
+ {
+ dcMem.MoveTo(rcItem.left, bottom);
+ dcMem.LineTo(rcItem.right, bottom);
+ }
+ else
+ {
+ dcMem.MoveTo(rcItem.left, top-1);
+ dcMem.LineTo(rcItem.right, top-1);
+ }
+ }
+ }
+
+ inline CRect CTab::GetCloseRect() const
+ {
+ CRect rcClose;
+ if (GetShowButtons())
+ {
+ rcClose= GetClientRect();
+ int Gap = 2;
+ int cx = GetSystemMetrics(SM_CXSMICON) -1;
+ int cy = GetSystemMetrics(SM_CYSMICON) -1;
+ rcClose.right -= Gap;
+ rcClose.left = rcClose.right - cx;
+
+ if (GetTabsAtTop())
+ rcClose.top = Gap;
+ else
+ rcClose.top = MAX(Gap, rcClose.bottom - m_nTabHeight);
+
+ rcClose.bottom = rcClose.top + cy;
+ }
+ return rcClose;
+ }
+
+ inline HMENU CTab::GetListMenu()
+ {
+ if (IsMenu(m_hListMenu))
+ ::DestroyMenu(m_hListMenu);
+
+ m_hListMenu = CreatePopupMenu();
+
+ // Add the menu items
+ for(UINT u = 0; u < MIN(GetAllTabs().size(), 9); ++u)
+ {
+ TCHAR szMenuString[MAX_MENU_STRING+1];
+ TCHAR szTabText[MAX_MENU_STRING];
+ lstrcpyn(szTabText, GetAllTabs()[u].szTabText, MAX_MENU_STRING -4);
+ wsprintf(szMenuString, _T("&%d %s"), u+1, szTabText);
+ AppendMenu(m_hListMenu, MF_STRING, IDW_FIRSTCHILD +u, szMenuString);
+ }
+ if (GetAllTabs().size() >= 10)
+ AppendMenu(m_hListMenu, MF_STRING, IDW_FIRSTCHILD +9, _T("More Windows"));
+
+ // Add a checkmark to the menu
+ int iSelected = GetCurSel();
+ if (iSelected < 9)
+ CheckMenuItem(m_hListMenu, iSelected, MF_BYPOSITION|MF_CHECKED);
+
+ return m_hListMenu;
+ }
+
+ inline CRect CTab::GetListRect() const
+ {
+ CRect rcList;
+ if (GetShowButtons())
+ {
+ CRect rcClose = GetCloseRect();
+ rcList = rcClose;
+ rcList.OffsetRect( -(rcClose.Width() + 2), 0);
+ rcList.InflateRect(-1, 0);
+ }
+ return rcList;
+ }
+
+ inline SIZE CTab::GetMaxTabSize() const
+ {
+ CSize Size;
+
+ for (int i = 0; i < TabCtrl_GetItemCount(m_hWnd); i++)
+ {
+ CClientDC dcClient(this);
+ dcClient.SelectObject(&m_Font);
+ std::vector<TCHAR> vTitle(MAX_MENU_STRING, _T('\0'));
+ TCHAR* pszTitle = &vTitle.front();
+ TCITEM tcItem = {0};
+ tcItem.mask = TCIF_TEXT |TCIF_IMAGE;
+ tcItem.cchTextMax = MAX_MENU_STRING;
+ tcItem.pszText = pszTitle;
+ TabCtrl_GetItem(m_hWnd, i, &tcItem);
+ CSize TempSize = dcClient.GetTextExtentPoint32(pszTitle, lstrlen(pszTitle));
+
+ int iImageSize = 0;
+ int iPadding = 6;
+ if (tcItem.iImage >= 0)
+ iImageSize = 20;
+ TempSize.cx += iImageSize + iPadding;
+
+ if (TempSize.cx > Size.cx)
+ Size = TempSize;
+ }
+
+ return Size;
+ }
+
+ inline BOOL CTab::GetTabsAtTop() const
+ // Returns TRUE if the contol's tabs are placed at the top
+ {
+ DWORD dwStyle = (DWORD)GetWindowLongPtr(GWL_STYLE);
+ return (!(dwStyle & TCS_BOTTOM));
+ }
+
+ inline int CTab::GetTextHeight() const
+ {
+ CClientDC dcClient(this);
+ dcClient.SelectObject(&m_Font);
+ CSize szText = dcClient.GetTextExtentPoint32(_T("Text"), lstrlen(_T("Text")));
+ return szText.cy;
+ }
+
+ inline int CTab::GetTabIndex(CWnd* pWnd) const
+ {
+ assert(pWnd);
+
+ for (int i = 0; i < (int)m_vTabPageInfo.size(); ++i)
+ {
+ if (m_vTabPageInfo[i].pView == pWnd)
+ return i;
+ }
+
+ return -1;
+ }
+
+ inline TabPageInfo CTab::GetTabPageInfo(UINT nTab) const
+ {
+ assert (nTab < m_vTabPageInfo.size());
+
+ return m_vTabPageInfo[nTab];
+ }
+
+ inline void CTab::NotifyChanged()
+ {
+ NMHDR nmhdr = {0};
+ nmhdr.hwndFrom = m_hWnd;
+ nmhdr.code = UWM_TAB_CHANGED;
+ GetParent()->SendMessage(WM_NOTIFY, 0L, (LPARAM)&nmhdr);
+ }
+
+ inline void CTab::OnCreate()
+ {
+ SetFont(&m_Font, TRUE);
+
+ // Assign ImageList unless we are owner drawn
+ if (!(GetWindowLongPtr(GWL_STYLE) & TCS_OWNERDRAWFIXED))
+ TabCtrl_SetImageList(m_hWnd, m_himlTab);
+
+ for (int i = 0; i < (int)m_vTabPageInfo.size(); ++i)
+ {
+ // Add tabs for each view.
+ TCITEM tie = {0};
+ tie.mask = TCIF_TEXT | TCIF_IMAGE;
+ tie.iImage = m_vTabPageInfo[i].iImage;
+ tie.pszText = m_vTabPageInfo[i].szTabText;
+ TabCtrl_InsertItem(m_hWnd, i, &tie);
+ }
+
+ int HeightGap = 5;
+ SetTabHeight(MAX(20, (GetTextHeight() + HeightGap)));
+ SelectPage(0);
+ }
+
+ inline void CTab::OnLButtonDown(WPARAM /*wParam*/, LPARAM lParam)
+ {
+ CPoint pt(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
+
+ if (GetCloseRect().PtInRect(pt))
+ {
+ m_IsClosePressed = TRUE;
+ SetCapture();
+ CClientDC dc(this);
+ DrawCloseButton(dc);
+ }
+ else
+ m_IsClosePressed = FALSE;
+
+ if (GetListRect().PtInRect(pt))
+ {
+ ShowListMenu();
+ }
+ }
+
+ inline void CTab::OnLButtonUp(WPARAM /*wParam*/, LPARAM lParam)
+ {
+ ReleaseCapture();
+ CPoint pt(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
+ if (m_IsClosePressed && GetCloseRect().PtInRect(pt))
+ {
+ RemoveTabPage(GetCurSel());
+ if (GetActiveView())
+ GetActiveView()->RedrawWindow();
+ }
+
+ m_IsClosePressed = FALSE;
+ }
+
+ inline void CTab::OnMouseLeave(WPARAM /*wParam*/, LPARAM /*lParam*/)
+ {
+ CClientDC dc(this);
+ DrawCloseButton(dc);
+ DrawListButton(dc);
+
+ m_IsTracking = FALSE;
+ }
+
+ inline void CTab::OnMouseMove(WPARAM /*wParam*/, LPARAM /*lParam*/)
+ {
+ if (!m_IsListMenuActive && m_IsListPressed)
+ {
+ m_IsListPressed = FALSE;
+ }
+
+ if (!m_IsTracking)
+ {
+ TRACKMOUSEEVENT TrackMouseEventStruct = {0};
+ TrackMouseEventStruct.cbSize = sizeof(TrackMouseEventStruct);
+ TrackMouseEventStruct.dwFlags = TME_LEAVE;
+ TrackMouseEventStruct.hwndTrack = m_hWnd;
+ _TrackMouseEvent(&TrackMouseEventStruct);
+ m_IsTracking = TRUE;
+ }
+
+ CClientDC dc(this);
+ DrawCloseButton(dc);
+ DrawListButton(dc);
+ }
+
+ inline LRESULT CTab::OnNCHitTest(WPARAM wParam, LPARAM lParam)
+ {
+ // Ensure we have an arrow cursor when the tab has no view window
+ if (0 == GetAllTabs().size())
+ SetCursor(LoadCursor(NULL, IDC_ARROW));
+
+ // Cause WM_LBUTTONUP and WM_LBUTTONDOWN messages to be sent for buttons
+ CPoint pt(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
+ ScreenToClient(pt);
+ if (GetCloseRect().PtInRect(pt)) return HTCLIENT;
+ if (GetListRect().PtInRect(pt)) return HTCLIENT;
+
+ return CWnd::WndProcDefault(WM_NCHITTEST, wParam, lParam);
+ }
+
+ inline LRESULT CTab::OnNotifyReflect(WPARAM wParam, LPARAM lParam)
+ {
+ UNREFERENCED_PARAMETER(wParam);
+
+ switch (((LPNMHDR)lParam)->code)
+ {
+ case TCN_SELCHANGE:
+ {
+ // Display the newly selected tab page
+ int nPage = GetCurSel();
+ ShowActiveView(m_vTabPageInfo[nPage].pView);
+ }
+ break;
+ }
+
+ return 0L;
+ }
+
+ inline void CTab::Paint()
+ {
+ // Microsoft's drawing for a tab control is rubbish, so we do our own.
+ // We use double buffering and regions to eliminate flicker
+
+ // Create the memory DC and bitmap
+ CClientDC dcView(this);
+ CMemDC dcMem(&dcView);
+ CRect rcClient = GetClientRect();
+ dcMem.CreateCompatibleBitmap(&dcView, rcClient.Width(), rcClient.Height());
+
+ if (0 == GetItemCount())
+ {
+ // No tabs, so simply display a grey background and exit
+ COLORREF rgbDialog = GetSysColor(COLOR_BTNFACE);
+ dcView.SolidFill(rgbDialog, rcClient);
+ return;
+ }
+
+ // Create a clipping region. Its the overall tab window's region,
+ // less the region belonging to the individual tab view's client area
+ CRgn rgnSrc1 = ::CreateRectRgn(rcClient.left, rcClient.top, rcClient.right, rcClient.bottom);
+ CRect rcTab = GetClientRect();
+ TabCtrl_AdjustRect(m_hWnd, FALSE, &rcTab);
+ if (rcTab.Height() < 0)
+ rcTab.top = rcTab.bottom;
+ if (rcTab.Width() < 0)
+ rcTab.left = rcTab.right;
+
+ CRgn rgnSrc2 = ::CreateRectRgn(rcTab.left, rcTab.top, rcTab.right, rcTab.bottom);
+ CRgn rgnClip = ::CreateRectRgn(0, 0, 0, 0);
+ ::CombineRgn(rgnClip, rgnSrc1, rgnSrc2, RGN_DIFF);
+
+ // Use the region in the memory DC to paint the grey background
+ dcMem.SelectClipRgn(&rgnClip);
+ HWND hWndParent = ::GetParent(m_hWnd);
+ CDC dcParent = ::GetDC(hWndParent);
+ HBRUSH hBrush = (HBRUSH) SendMessage(hWndParent, WM_CTLCOLORDLG, (WPARAM)dcParent.GetHDC(), (LPARAM)hWndParent);
+ dcMem.SelectObject(FromHandle(hBrush));
+ dcMem.PaintRgn(&rgnClip);
+
+ // Draw the tab buttons on the memory DC:
+ DrawTabs(dcMem);
+
+ // Draw buttons and tab borders
+ DrawCloseButton(dcMem);
+ DrawListButton(dcMem);
+ DrawTabBorders(dcMem, rcTab);
+
+ // Now copy our from our memory DC to the window DC
+ dcView.SelectClipRgn(&rgnClip);
+ dcView.BitBlt(0, 0, rcClient.Width(), rcClient.Height(), &dcMem, 0, 0, SRCCOPY);
+ }
+
+ inline void CTab::PreCreate(CREATESTRUCT &cs)
+ {
+ // For Tabs on the bottom, add the TCS_BOTTOM style
+ cs.style = WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_VISIBLE;
+ }
+
+ inline void CTab::PreRegisterClass(WNDCLASS &wc)
+ {
+ wc.lpszClassName = WC_TABCONTROL;
+ }
+
+ inline void CTab::RecalcLayout()
+ {
+ if (IsWindow())
+ {
+ if (GetActiveView())
+ {
+ // Set the tab sizes
+ SetTabSize();
+
+ // Position the View over the tab control's display area
+ CRect rc = GetClientRect();
+ TabCtrl_AdjustRect(m_hWnd, FALSE, &rc);
+ GetActiveView()->SetWindowPos(NULL, rc, SWP_SHOWWINDOW);
+ }
+ else
+ RedrawWindow();
+ }
+ }
+
+ inline void CTab::RemoveTabPage(int nPage)
+ {
+ if ((nPage < 0) || (nPage > (int)m_vTabPageInfo.size() -1))
+ return;
+
+ // Remove the tab
+ TabCtrl_DeleteItem(m_hWnd, nPage);
+
+ // Remove the TapPageInfo entry
+ std::vector<TabPageInfo>::iterator itTPI = m_vTabPageInfo.begin() + nPage;
+ CWnd* pView = (*itTPI).pView;
+ int iImage = (*itTPI).iImage;
+ if (iImage >= 0)
+ TabCtrl_RemoveImage(m_hWnd, iImage);
+
+ if (pView == m_pActiveView)
+ m_pActiveView = 0;
+
+ (*itTPI).pView->Destroy();
+ m_vTabPageInfo.erase(itTPI);
+
+ std::vector<WndPtr>::iterator itView;
+ for (itView = m_vTabViews.begin(); itView < m_vTabViews.end(); ++itView)
+ {
+ if ((*itView).get() == pView)
+ {
+ m_vTabViews.erase(itView);
+ break;
+ }
+ }
+
+ if (IsWindow())
+ {
+ if (m_vTabPageInfo.size() > 0)
+ {
+ SetTabSize();
+ SelectPage(0);
+ }
+ else
+ ShowActiveView(NULL);
+
+ NotifyChanged();
+ }
+ }
+
+ inline void CTab::SelectPage(int nPage)
+ {
+ if ((nPage >= 0) && (nPage < GetItemCount()))
+ {
+ if (nPage != GetCurSel())
+ SetCurSel(nPage);
+
+ ShowActiveView(m_vTabPageInfo[nPage].pView);
+ }
+ }
+
+ inline void CTab::SetFixedWidth(BOOL bEnabled)
+ {
+ DWORD dwStyle = (DWORD)GetWindowLongPtr(GWL_STYLE);
+ if (bEnabled)
+ SetWindowLongPtr(GWL_STYLE, dwStyle | TCS_FIXEDWIDTH);
+ else
+ SetWindowLongPtr(GWL_STYLE, dwStyle & ~TCS_FIXEDWIDTH);
+
+ RecalcLayout();
+ }
+
+ inline void CTab::SetOwnerDraw(BOOL bEnabled)
+ // Enable or disable owner draw
+ {
+ DWORD dwStyle = (DWORD)GetWindowLongPtr(GWL_STYLE);
+ if (bEnabled)
+ {
+ SetWindowLongPtr(GWL_STYLE, dwStyle | TCS_OWNERDRAWFIXED);
+ TabCtrl_SetImageList(m_hWnd, NULL);
+ }
+ else
+ {
+ SetWindowLongPtr(GWL_STYLE, dwStyle & ~TCS_OWNERDRAWFIXED);
+ TabCtrl_SetImageList(m_hWnd, m_himlTab);
+ }
+
+ RecalcLayout();
+ }
+
+ inline void CTab::SetShowButtons(BOOL bShow)
+ {
+ m_bShowButtons = bShow;
+ RecalcLayout();
+ }
+
+ inline void CTab::SetTabIcon(int i, HICON hIcon)
+ // Changes or sets the tab's icon
+ {
+ assert (GetItemCount() > i);
+ TCITEM tci = {0};
+ tci.mask = TCIF_IMAGE;
+ GetItem(i, &tci);
+ if (tci.iImage >= 0)
+ {
+ ImageList_ReplaceIcon(GetImageList(), i, hIcon);
+ }
+ else
+ {
+ int iImage = ImageList_AddIcon(GetImageList(), hIcon);
+ tci.iImage = iImage;
+ TabCtrl_SetItem(m_hWnd, i, &tci);
+ m_vTabPageInfo[i].iImage = iImage;
+ }
+ }
+
+ inline void CTab::SetTabsAtTop(BOOL bTop)
+ // Positions the tabs at the top or botttom of the control
+ {
+ DWORD dwStyle = (DWORD)GetWindowLongPtr(GWL_STYLE);
+
+ if (bTop)
+ dwStyle &= ~TCS_BOTTOM;
+ else
+ dwStyle |= TCS_BOTTOM;
+
+ SetWindowLongPtr(GWL_STYLE, dwStyle);
+ RecalcLayout();
+ }
+
+ inline void CTab::SetTabSize()
+ {
+ if (GetItemCount() > 0)
+ {
+ CRect rc = GetClientRect();
+ TabCtrl_AdjustRect(m_hWnd, FALSE, &rc);
+
+ int xGap = 2;
+ if (m_bShowButtons) xGap += GetCloseRect().Width() + GetListRect().Width() +2;
+
+ int nItemWidth = MIN( GetMaxTabSize().cx, (rc.Width() - xGap)/GetItemCount() );
+ nItemWidth = MAX(nItemWidth, 0);
+ SendMessage(TCM_SETITEMSIZE, 0L, MAKELPARAM(nItemWidth, m_nTabHeight));
+ NotifyChanged();
+ }
+ }
+
+ inline void CTab::SetTabText(UINT nTab, LPCTSTR szText)
+ {
+ // Allows the text to be changed on an existing tab
+ if (nTab < GetAllTabs().size())
+ {
+ TCITEM Item = {0};
+ std::vector<TCHAR> vTChar(MAX_MENU_STRING+1, _T('\0'));
+ TCHAR* pTChar = &vTChar.front();
+ lstrcpyn(pTChar, szText, MAX_MENU_STRING);
+ Item.mask = TCIF_TEXT;
+ Item.pszText = pTChar;
+
+ if (TabCtrl_SetItem(m_hWnd, nTab, &Item))
+ lstrcpyn(m_vTabPageInfo[nTab].szTabText, pTChar, MAX_MENU_STRING);
+ }
+ }
+
+ inline void CTab::ShowActiveView(CWnd* pView)
+ // Sets or changes the View window displayed within the tab page
+ {
+ // Hide the old view
+ if (GetActiveView() && (GetActiveView()->IsWindow()))
+ GetActiveView()->ShowWindow(SW_HIDE);
+
+ // Assign the view window
+ m_pActiveView = pView;
+
+ if (m_pActiveView && m_hWnd)
+ {
+ if (!m_pActiveView->IsWindow())
+ {
+ // The tab control is already created, so create the new view too
+ GetActiveView()->Create(this);
+ }
+
+ // Position the View over the tab control's display area
+ CRect rc = GetClientRect();
+ TabCtrl_AdjustRect(m_hWnd, FALSE, &rc);
+ GetActiveView()->SetWindowPos(HWND_TOP, rc, SWP_SHOWWINDOW);
+ GetActiveView()->SetFocus();
+ }
+ }
+
+ inline void CTab::ShowListMenu()
+ // Displays the list of windows in a popup menu
+ {
+ if (!m_IsListPressed)
+ {
+ m_IsListPressed = TRUE;
+ HMENU hMenu = GetListMenu();
+
+ CPoint pt(GetListRect().left, GetListRect().top + GetTabHeight());
+ ClientToScreen(pt);
+
+ // Choosing the frame's hwnd for the menu's messages will automatically theme the popup menu
+ HWND MenuHwnd = GetAncestor()->GetHwnd();
+ int nPage = 0;
+ m_IsListMenuActive = TRUE;
+ nPage = TrackPopupMenuEx(hMenu, TPM_LEFTALIGN | TPM_TOPALIGN | TPM_RETURNCMD, pt.x, pt.y, MenuHwnd, NULL) - IDW_FIRSTCHILD;
+ if ((nPage >= 0) && (nPage < 9)) SelectPage(nPage);
+ if (nPage == 9) ShowListDialog();
+ m_IsListMenuActive = FALSE;
+ }
+
+ CClientDC dc(this);
+ DrawListButton(dc);
+ }
+
+ inline void CTab::ShowListDialog()
+ {
+ // Definition of a dialog template which displays a List Box
+ unsigned char dlg_Template[] =
+ {
+ 0x01,0x00,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0xc8,0x00,0xc8,0x90,0x03,
+ 0x00,0x00,0x00,0x00,0x00,0xdc,0x00,0x8e,0x00,0x00,0x00,0x00,0x00,0x53,0x00,0x65,
+ 0x00,0x6c,0x00,0x65,0x00,0x63,0x00,0x74,0x00,0x20,0x00,0x57,0x00,0x69,0x00,0x6e,
+ 0x00,0x64,0x00,0x6f,0x00,0x77,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x01,0x4d,
+ 0x00,0x53,0x00,0x20,0x00,0x53,0x00,0x68,0x00,0x65,0x00,0x6c,0x00,0x6c,0x00,0x20,
+ 0x00,0x44,0x00,0x6c,0x00,0x67,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x01,0x00,0x01,0x50,0x40,0x00,0x7a,0x00,0x25,0x00,0x0f,0x00,0x01,
+ 0x00,0x00,0x00,0xff,0xff,0x80,0x00,0x4f,0x00,0x4b,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x50,0x7a,0x00,0x7a,0x00,0x25,
+ 0x00,0x0f,0x00,0x02,0x00,0x00,0x00,0xff,0xff,0x80,0x00,0x43,0x00,0x61,0x00,0x6e,
+ 0x00,0x63,0x00,0x65,0x00,0x6c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x02,0x00,0x01,0x01,0x21,0x50,0x06,0x00,0x06,0x00,0xcf,0x00,0x6d,0x00,0x79,
+ 0x00,0x00,0x00,0xff,0xff,0x83,0x00,0x00,0x00,0x00,0x00
+ };
+
+ // Display the modal dialog. The dialog is defined in the dialog template rather
+ // than in the resource script (rc) file.
+ CSelectDialog MyDialog((LPCDLGTEMPLATE) dlg_Template);
+ for(UINT u = 0; u < GetAllTabs().size(); ++u)
+ {
+ MyDialog.AddItem(GetAllTabs()[u].szTabText);
+ }
+
+ int iSelected = (int)MyDialog.DoModal();
+ if (iSelected >= 0) SelectPage(iSelected);
+ }
+
+ inline void CTab::SwapTabs(UINT nTab1, UINT nTab2)
+ {
+ if ((nTab1 < GetAllTabs().size()) && (nTab2 < GetAllTabs().size()) && (nTab1 != nTab2))
+ {
+ int nPage = GetCurSel();
+ TabPageInfo T1 = GetTabPageInfo(nTab1);
+ TabPageInfo T2 = GetTabPageInfo(nTab2);
+
+ TCITEM Item1 = {0};
+ Item1.mask = TCIF_IMAGE | TCIF_PARAM | TCIF_RTLREADING | TCIF_STATE | TCIF_TEXT;
+ GetItem(nTab1, &Item1);
+ TCITEM Item2 = {0};
+ Item2.mask = TCIF_IMAGE | TCIF_PARAM | TCIF_RTLREADING | TCIF_STATE | TCIF_TEXT;
+ GetItem(nTab2, &Item2);
+ TabCtrl_SetItem(m_hWnd, nTab1, &Item2);
+ TabCtrl_SetItem(m_hWnd, nTab2, &Item1);
+
+ m_vTabPageInfo[nTab1] = T2;
+ m_vTabPageInfo[nTab2] = T1;
+ SelectPage(nPage);
+ }
+ }
+
+ inline LRESULT CTab::WndProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam)
+ {
+ switch(uMsg)
+ {
+ case WM_PAINT:
+ if (GetWindowLongPtr(GWL_STYLE) & TCS_OWNERDRAWFIXED)
+ {
+ // Remove all pending paint requests
+ PAINTSTRUCT ps;
+ BeginPaint(ps);
+ EndPaint(ps);
+
+ // Now call our local Paint
+ Paint();
+ return 0;
+ }
+ break;
+
+ case WM_ERASEBKGND:
+ if (GetWindowLongPtr(GWL_STYLE) & TCS_OWNERDRAWFIXED)
+ return 0;
+ break;
+ case WM_KILLFOCUS:
+ m_IsClosePressed = FALSE;
+ break;
+ case WM_LBUTTONDBLCLK:
+ case WM_LBUTTONDOWN:
+ OnLButtonDown(wParam, lParam);
+ break;
+ case WM_LBUTTONUP:
+ OnLButtonUp(wParam, lParam);
+ break;
+ case WM_MOUSEMOVE:
+ OnMouseMove(wParam, lParam);
+ break;
+ case WM_MOUSELEAVE:
+ OnMouseLeave(wParam, lParam);
+ break;
+ case WM_NCHITTEST:
+ return OnNCHitTest(wParam, lParam);
+
+ case WM_WINDOWPOSCHANGING:
+ // A little hack to reduce tab flicker
+ if (IsWindowVisible() && (GetWindowLongPtr(GWL_STYLE) & TCS_OWNERDRAWFIXED))
+ {
+ LPWINDOWPOS pWinPos = (LPWINDOWPOS)lParam;
+ pWinPos->flags |= SWP_NOREDRAW;
+
+ Paint();
+ }
+
+ break;
+
+ case WM_WINDOWPOSCHANGED:
+ RecalcLayout();
+ break;
+ }
+
+ // pass unhandled messages on for default processing
+ return CWnd::WndProcDefault(uMsg, wParam, lParam);
+ }
+
+ // Wrappers for Win32 Macros
+ inline void CTab::AdjustRect(BOOL fLarger, RECT *prc) const
+ {
+ assert(::IsWindow(m_hWnd));
+ TabCtrl_AdjustRect(m_hWnd, fLarger, prc);
+ }
+
+ inline int CTab::GetCurFocus() const
+ {
+ assert(::IsWindow(m_hWnd));
+ return TabCtrl_GetCurFocus(m_hWnd);
+ }
+
+ inline int CTab::GetCurSel() const
+ {
+ assert(::IsWindow(m_hWnd));
+ return TabCtrl_GetCurSel(m_hWnd);
+ }
+
+ inline BOOL CTab::GetItem(int iItem, LPTCITEM pitem) const
+ {
+ assert(::IsWindow(m_hWnd));
+ return TabCtrl_GetItem(m_hWnd, iItem, pitem);
+ }
+
+ inline int CTab::GetItemCount() const
+ {
+ assert(::IsWindow(m_hWnd));
+ return TabCtrl_GetItemCount(m_hWnd);
+ }
+
+ inline int CTab::HitTest(TCHITTESTINFO& info) const
+ {
+ assert(::IsWindow(m_hWnd));
+ return TabCtrl_HitTest(m_hWnd, &info);
+ }
+
+ inline void CTab::SetCurFocus(int iItem) const
+ {
+ assert(::IsWindow(m_hWnd));
+ TabCtrl_SetCurFocus(m_hWnd, iItem);
+ }
+
+ inline int CTab::SetCurSel(int iItem) const
+ {
+ assert(::IsWindow(m_hWnd));
+ return TabCtrl_SetCurSel(m_hWnd, iItem);
+ }
+
+ inline DWORD CTab::SetItemSize(int cx, int cy) const
+ {
+ assert(::IsWindow(m_hWnd));
+ return TabCtrl_SetItemSize(m_hWnd, cx, cy);
+ }
+
+ inline int CTab::SetMinTabWidth(int cx) const
+ {
+ assert(::IsWindow(m_hWnd));
+ return TabCtrl_SetMinTabWidth(m_hWnd, cx);
+ }
+
+ inline void CTab::SetPadding(int cx, int cy) const
+ {
+ assert(::IsWindow(m_hWnd));
+ TabCtrl_SetPadding(m_hWnd, cx, cy);
+ }
+
+ ////////////////////////////////////////
+ // Definitions for the CTabbedMDI class
+ inline CTabbedMDI::CTabbedMDI()
+ {
+ GetTab().SetShowButtons(TRUE);
+ }
+
+ inline CTabbedMDI::~CTabbedMDI()
+ {
+ }
+
+ inline CWnd* CTabbedMDI::AddMDIChild(CWnd* pView, LPCTSTR szTabText, int idMDIChild /*= 0*/)
+ {
+ assert(pView);
+ assert(lstrlen(szTabText) < MAX_MENU_STRING);
+
+ GetTab().AddTabPage(WndPtr(pView), szTabText, 0, idMDIChild);
+
+ // Fake a WM_MOUSEACTIVATE to propogate focus change to dockers
+ if (IsWindow())
+ GetParent()->SendMessage(WM_MOUSEACTIVATE, (WPARAM)GetAncestor(), MAKELPARAM(HTCLIENT,WM_LBUTTONDOWN));
+
+ return pView;
+ }
+
+ inline void CTabbedMDI::CloseActiveMDI()
+ {
+ int nTab = GetTab().GetCurSel();
+ if (nTab >= 0)
+ GetTab().RemoveTabPage(nTab);
+
+ RecalcLayout();
+ }
+
+ inline void CTabbedMDI::CloseAllMDIChildren()
+ {
+ while (GetMDIChildCount() > 0)
+ {
+ GetTab().RemoveTabPage(0);
+ }
+ }
+
+ inline void CTabbedMDI::CloseMDIChild(int nTab)
+ {
+ GetTab().RemoveTabPage(nTab);
+
+ if (GetActiveMDIChild())
+ GetActiveMDIChild()->RedrawWindow();
+ }
+
+ inline HWND CTabbedMDI::Create(CWnd* pParent /* = NULL*/)
+ {
+ CLIENTCREATESTRUCT clientcreate ;
+ clientcreate.hWindowMenu = m_hWnd;
+ clientcreate.idFirstChild = IDW_FIRSTCHILD ;
+ DWORD dwStyle = WS_CHILD | WS_VISIBLE | MDIS_ALLCHILDSTYLES;
+
+ // Create the MDICLIENT view window
+ if (!CreateEx(0, _T("MDICLIENT"), _T(""),
+ dwStyle, 0, 0, 0, 0, pParent, NULL, (PSTR) &clientcreate))
+ throw CWinException(_T("CMDIClient::Create ... CreateEx failed"));
+
+ return m_hWnd;
+ }
+
+ inline CWnd* CTabbedMDI::GetActiveMDIChild() const
+ {
+ CWnd* pView = NULL;
+ int nTab = GetTab().GetCurSel();
+ if (nTab >= 0)
+ {
+ TabPageInfo tbi = GetTab().GetTabPageInfo(nTab);
+ pView = tbi.pView;
+ }
+
+ return pView;
+ }
+
+ inline int CTabbedMDI::GetActiveMDITab() const
+ {
+ return GetTab().GetCurSel();
+ }
+
+ inline CWnd* CTabbedMDI::GetMDIChild(int nTab) const
+ {
+ assert(nTab >= 0);
+ assert(nTab < GetMDIChildCount());
+ return GetTab().GetTabPageInfo(nTab).pView;
+ }
+
+ inline int CTabbedMDI::GetMDIChildCount() const
+ {
+ return (int) GetTab().GetAllTabs().size();
+ }
+
+ inline int CTabbedMDI::GetMDIChildID(int nTab) const
+ {
+ assert(nTab >= 0);
+ assert(nTab < GetMDIChildCount());
+ return GetTab().GetTabPageInfo(nTab).idTab;
+ }
+
+ inline LPCTSTR CTabbedMDI::GetMDIChildTitle(int nTab) const
+ {
+ assert(nTab >= 0);
+ assert(nTab < GetMDIChildCount());
+ return GetTab().GetTabPageInfo(nTab).szTabText;
+ }
+
+ inline BOOL CTabbedMDI::LoadRegistrySettings(tString tsRegistryKeyName)
+ {
+ BOOL bResult = FALSE;
+
+ if (0 != tsRegistryKeyName.size())
+ {
+ tString tsKey = _T("Software\\") + tsRegistryKeyName + _T("\\MDI Children");
+ HKEY hKey = 0;
+ RegOpenKeyEx(HKEY_CURRENT_USER, tsKey.c_str(), 0, KEY_READ, &hKey);
+ if (hKey)
+ {
+ DWORD dwType = REG_BINARY;
+ DWORD BufferSize = sizeof(TabPageInfo);
+ TabPageInfo tbi = {0};
+ int i = 0;
+ TCHAR szNumber[16];
+ tString tsSubKey = _T("MDI Child ");
+ tsSubKey += _itot(i, szNumber, 10);
+
+ // Fill the DockList vector from the registry
+ while (0 == RegQueryValueEx(hKey, tsSubKey.c_str(), NULL, &dwType, (LPBYTE)&tbi, &BufferSize))
+ {
+ CWnd* pWnd = NewMDIChildFromID(tbi.idTab);
+ if (pWnd)
+ {
+ AddMDIChild(pWnd, tbi.szTabText, tbi.idTab);
+ i++;
+ tsSubKey = _T("MDI Child ");
+ tsSubKey += _itot(i, szNumber, 10);
+ bResult = TRUE;
+ }
+ else
+ {
+ TRACE(_T("Failed to get TabbedMDI info from registry"));
+ bResult = FALSE;
+ break;
+ }
+ }
+
+ // Load Active MDI Tab from the registry
+ tsSubKey = _T("Active MDI Tab");
+ int nTab;
+ dwType = REG_DWORD;
+ BufferSize = sizeof(int);
+ if(ERROR_SUCCESS == RegQueryValueEx(hKey, tsSubKey.c_str(), NULL, &dwType, (LPBYTE)&nTab, &BufferSize))
+ SetActiveMDITab(nTab);
+ else
+ SetActiveMDITab(0);
+
+ RegCloseKey(hKey);
+ }
+ }
+
+ if (!bResult)
+ CloseAllMDIChildren();
+
+ return bResult;
+ }
+
+ inline CWnd* CTabbedMDI::NewMDIChildFromID(int /*idMDIChild*/)
+ {
+ // Override this function to create new MDI children from IDs as shown below
+ CWnd* pView = NULL;
+ /* switch(idTab)
+ {
+ case ID_SIMPLE:
+ pView = new CViewSimple;
+ break;
+ case ID_RECT:
+ pView = new CViewRect;
+ break;
+ default:
+ TRACE(_T("Unknown MDI child ID\n"));
+ break;
+ } */
+
+ return pView;
+ }
+
+ inline void CTabbedMDI::OnCreate()
+ {
+ GetTab().Create(this);
+ GetTab().SetFixedWidth(TRUE);
+ GetTab().SetOwnerDraw(TRUE);
+ }
+
+ inline void CTabbedMDI::OnDestroy(WPARAM /*wParam*/, LPARAM /*lParam*/ )
+ {
+ CloseAllMDIChildren();
+ }
+
+ inline LRESULT CTabbedMDI::OnNotify(WPARAM /*wParam*/, LPARAM lParam)
+ {
+ LPNMHDR pnmhdr = (LPNMHDR)lParam;
+ if (pnmhdr->code == UWM_TAB_CHANGED)
+ RecalcLayout();
+
+ return 0L;
+ }
+
+ inline void CTabbedMDI::OnWindowPosChanged(WPARAM /*wParam*/, LPARAM /*lParam*/)
+ {
+ RecalcLayout();
+ }
+
+ inline void CTabbedMDI::RecalcLayout()
+ {
+ if (GetTab().IsWindow())
+ {
+ if (GetTab().GetItemCount() >0)
+ {
+ CRect rcClient = GetClientRect();
+ GetTab().SetWindowPos(NULL, rcClient, SWP_SHOWWINDOW);
+ GetTab().UpdateWindow();
+ }
+ else
+ {
+ CRect rcClient = GetClientRect();
+ GetTab().SetWindowPos(NULL, rcClient, SWP_HIDEWINDOW);
+ Invalidate();
+ }
+ }
+ }
+
+ inline BOOL CTabbedMDI::SaveRegistrySettings(tString tsRegistryKeyName)
+ {
+ if (0 != tsRegistryKeyName.size())
+ {
+ tString tsKeyName = _T("Software\\") + tsRegistryKeyName;
+ HKEY hKey = NULL;
+ HKEY hKeyMDIChild = NULL;
+
+ try
+ {
+ if (ERROR_SUCCESS != RegCreateKeyEx(HKEY_CURRENT_USER, tsKeyName.c_str(), 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, NULL))
+ throw (CWinException(_T("RegCreateKeyEx Failed")));
+
+ RegDeleteKey(hKey, _T("MDI Children"));
+ if (ERROR_SUCCESS != RegCreateKeyEx(hKey, _T("MDI Children"), 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKeyMDIChild, NULL))
+ throw (CWinException(_T("RegCreateKeyEx Failed")));
+
+ for (int i = 0; i < GetMDIChildCount(); ++i)
+ {
+ TCHAR szNumber[16];
+ tString tsSubKey = _T("MDI Child ");
+ tsSubKey += _itot(i, szNumber, 10);
+ TabPageInfo pdi = GetTab().GetTabPageInfo(i);
+ if (ERROR_SUCCESS != RegSetValueEx(hKeyMDIChild, tsSubKey.c_str(), 0, REG_BINARY, (LPBYTE)&pdi, sizeof(TabPageInfo)))
+ throw (CWinException(_T("RegSetValueEx Failed")));
+ }
+
+ // Add Active Tab to the registry
+ tString tsSubKey = _T("Active MDI Tab");
+ int nTab = GetActiveMDITab();
+ if(ERROR_SUCCESS != RegSetValueEx(hKeyMDIChild, tsSubKey.c_str(), 0, REG_DWORD, (LPBYTE)&nTab, sizeof(int)))
+ throw (CWinException(_T("RegSetValueEx failed")));
+
+ RegCloseKey(hKeyMDIChild);
+ RegCloseKey(hKey);
+ }
+ catch (const CWinException& e)
+ {
+ // Roll back the registry changes by deleting the subkeys
+ if (hKey)
+ {
+ if (hKeyMDIChild)
+ {
+ RegDeleteKey(hKeyMDIChild, _T("MDI Children"));
+ RegCloseKey(hKeyMDIChild);
+ }
+
+ RegDeleteKey(HKEY_CURRENT_USER ,tsKeyName.c_str());
+ RegCloseKey(hKey);
+ }
+
+ e.what();
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+ }
+
+ inline void CTabbedMDI::SetActiveMDIChild(CWnd* pWnd)
+ {
+ assert(pWnd);
+ int nPage = GetTab().GetTabIndex(pWnd);
+ if (nPage >= 0)
+ GetTab().SelectPage(nPage);
+ }
+
+ inline void CTabbedMDI::SetActiveMDITab(int iTab)
+ {
+ assert(::IsWindow(m_hWnd));
+ assert(GetTab().IsWindow());
+ GetTab().SelectPage(iTab);
+ }
+
+ inline LRESULT CTabbedMDI::WndProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam)
+ {
+ switch(uMsg)
+ {
+ case WM_DESTROY:
+ OnDestroy(wParam, lParam);
+ break;
+
+ case WM_WINDOWPOSCHANGED:
+ OnWindowPosChanged(wParam, lParam);
+ break;
+ }
+
+ return CWnd::WndProcDefault(uMsg, wParam, lParam);
+ }
+
+} // namespace Win32xx
+
+#endif // _WIN32XX_TAB_H_
diff --git a/mmc_updater/depends/win32cpp/taskdialog.h b/mmc_updater/depends/win32cpp/taskdialog.h
new file mode 100644
index 00000000..2285d1e1
--- /dev/null
+++ b/mmc_updater/depends/win32cpp/taskdialog.h
@@ -0,0 +1,811 @@
+// Win32++ Version 7.2
+// Released: 5th AUgust 2011
+//
+// David Nash
+// email: dnash@bigpond.net.au
+// url: https://sourceforge.net/projects/win32-framework
+//
+//
+// Copyright (c) 2005-2011 David Nash
+//
+// Permission is hereby granted, free of charge, to
+// any person obtaining a copy of this software and
+// associated documentation files (the "Software"),
+// to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify,
+// merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom
+// the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice
+// shall be included in all copies or substantial portions
+// of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
+// OR OTHER DEALINGS IN THE SOFTWARE.
+//
+////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////
+// taskdialog.h
+// Declaration of the CTaskDialog class
+
+// A task dialog is a dialog box that can be used to display information
+// and receive simple input from the user. Like a message box, it is
+// formatted by the operating system according to parameters you set.
+// However, a task dialog has many more features than a message box.
+
+// NOTES:
+// Task Dialogs are only supported on Windows Vista and above.
+// Task Dialogs require XP themes enabled (use version 6 of Common Controls)
+// Task Dialogs are always modal.
+
+
+#ifndef _WIN32XX_TASKDIALOG_H_
+#define _WIN32XX_TASKDIALOG_H_
+
+#include "wincore.h"
+
+namespace Win32xx
+{
+
+ class CTaskDialog : public CWnd
+ {
+ public:
+ CTaskDialog();
+ virtual ~CTaskDialog() {}
+
+ void AddCommandControl(int nButtonID, LPCTSTR pszCaption);
+ void AddRadioButton(int nRadioButtonID, LPCTSTR pszCaption);
+ void AddRadioButtonGroup(int nIDRadioButtonsFirst, int nIDRadioButtonsLast);
+ void ClickButton(int nButtonID) const;
+ void ClickRadioButton(int nRadioButtonID) const;
+ LRESULT DoModal(CWnd* pParent = NULL);
+ void ElevateButton(int nButtonID, BOOL bElevated);
+ void EnableButton(int nButtonID, BOOL bEnabled);
+ void EnableRadioButton(int nButtonID, BOOL bEnabled);
+ TASKDIALOGCONFIG GetConfig() const;
+ TASKDIALOG_FLAGS GetOptions() const;
+ int GetSelectedButtonID() const;
+ int GetSelectedRadioButtonID() const;
+ BOOL GetVerificationCheckboxState() const;
+ static BOOL IsSupported();
+ void NavigateTo(CTaskDialog& TaskDialog) const;
+ void RemoveAllButtons();
+ void RemoveAllRadioButtons();
+ void Reset();
+ void SetCommonButtons(TASKDIALOG_COMMON_BUTTON_FLAGS dwCommonButtons);
+ void SetContent(LPCTSTR pszContent);
+ void SetDefaultButton(int nButtonID);
+ void SetDefaultRadioButton(int nRadioButtonID);
+ void SetDialogWidth(UINT nWidth = 0);
+ void SetExpansionArea(LPCTSTR pszExpandedInfo, LPCTSTR pszExpandedLabel = _T(""), LPCTSTR pszCollapsedLabel = _T(""));
+ void SetFooterIcon(HICON hFooterIcon);
+ void SetFooterIcon(LPCTSTR lpszFooterIcon);
+ void SetFooterText(LPCTSTR pszFooter);
+ void SetMainIcon(HICON hMainIcon);
+ void SetMainIcon(LPCTSTR lpszMainIcon);
+ void SetMainInstruction(LPCTSTR pszMainInstruction);
+ void SetOptions(TASKDIALOG_FLAGS dwFlags);
+ void SetProgressBarMarquee(BOOL bEnabled = TRUE, int nMarqueeSpeed = 0);
+ void SetProgressBarPosition(int nProgressPos);
+ void SetProgressBarRange(int nMinRange, int nMaxRange);
+ void SetProgressBarState(int nNewState = PBST_NORMAL);
+ void SetVerificationCheckbox(BOOL bChecked);
+ void SetVerificationCheckboxText(LPCTSTR pszVerificationText);
+ void SetWindowTitle(LPCTSTR pszWindowTitle);
+ static HRESULT CALLBACK StaticTaskDialogProc(HWND hWnd, UINT uNotification, WPARAM wParam, LPARAM lParam, LONG_PTR dwRefData);
+ void StoreText(std::vector<WCHAR>& vWChar, LPCTSTR pFromTChar);
+ void UpdateElementText(TASKDIALOG_ELEMENTS eElement, LPCTSTR pszNewText);
+
+
+ protected:
+ // Override these functions as required
+ virtual BOOL OnTDButtonClicked(int nButtonID);
+ virtual void OnTDConstructed();
+ virtual void OnTDCreated();
+ virtual void OnTDDestroyed();
+ virtual void OnTDExpandButtonClicked(BOOL bExpanded);
+ virtual void OnTDHelp();
+ virtual void OnTDHyperlinkClicked(LPCTSTR pszHref);
+ virtual void OnTDNavigatePage();
+ virtual BOOL OnTDRadioButtonClicked(int nRadioButtonID);
+ virtual BOOL OnTDTimer(DWORD dwTickCount);
+ virtual void OnTDVerificationCheckboxClicked(BOOL bChecked);
+ virtual LRESULT TaskDialogProc(UINT uMsg, WPARAM wParam, LPARAM lParam);
+ virtual LRESULT TaskDialogProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam);
+
+ private:
+ CTaskDialog(const CTaskDialog&); // Disable copy construction
+ CTaskDialog& operator = (const CTaskDialog&); // Disable assignment operator
+
+ std::vector<TASKDIALOG_BUTTON> m_vButtons;
+ std::vector<TASKDIALOG_BUTTON> m_vRadioButtons;
+
+ std::vector< std::vector<WCHAR> > m_vButtonsText; // A vector of WCHAR vectors
+ std::vector< std::vector<WCHAR> > m_vRadioButtonsText; // A vector of WCHAR vectors
+
+ std::vector<WCHAR> m_vWindowTitle;
+ std::vector<WCHAR> m_vMainInstruction;
+ std::vector<WCHAR> m_vContent;
+ std::vector<WCHAR> m_vVerificationText;
+ std::vector<WCHAR> m_vExpandedInformation;
+ std::vector<WCHAR> m_vExpandedControlText;
+ std::vector<WCHAR> m_vCollapsedControlText;
+ std::vector<WCHAR> m_vFooter;
+
+ TASKDIALOGCONFIG m_tc;
+ int m_SelectedButtonID;
+ int m_SelectedRadioButtonID;
+ BOOL m_VerificationCheckboxState;
+ };
+
+}
+
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+namespace Win32xx
+{
+
+ inline CTaskDialog::CTaskDialog() : m_SelectedButtonID(0), m_SelectedRadioButtonID(0), m_VerificationCheckboxState(FALSE)
+ {
+ ZeroMemory(&m_tc, sizeof(m_tc));
+ m_tc.cbSize = sizeof(m_tc);
+ m_tc.pfCallback = CTaskDialog::StaticTaskDialogProc;
+ }
+
+ inline void CTaskDialog::AddCommandControl(int nButtonID, LPCTSTR pszCaption)
+ // Adds a command control or push button to the Task Dialog.
+ {
+ assert (m_hWnd == NULL);
+
+ std::vector<WCHAR> vButtonText;
+ StoreText(vButtonText, pszCaption);
+ m_vButtonsText.push_back(vButtonText); // m_vButtonsText is a vector of vector<WCHAR>'s
+
+ TASKDIALOG_BUTTON tdb;
+ tdb.nButtonID = nButtonID;
+ tdb.pszButtonText = &m_vButtonsText.back().front();
+
+ m_vButtons.push_back(tdb);
+ }
+
+ inline void CTaskDialog::AddRadioButton(int nRadioButtonID, LPCTSTR pszCaption)
+ // Adds a radio button to the Task Dialog.
+ {
+ assert (m_hWnd == NULL);
+
+ std::vector<WCHAR> vRadioButtonText;
+ StoreText(vRadioButtonText, pszCaption);
+ m_vRadioButtonsText.push_back(vRadioButtonText); // m_vRadioButtonsText is a vector of vector<WCHAR>'s
+
+ TASKDIALOG_BUTTON tdb;
+ tdb.nButtonID = nRadioButtonID;
+ tdb.pszButtonText = &m_vRadioButtonsText.back().front();
+
+ m_vRadioButtons.push_back(tdb);
+ }
+
+ inline void CTaskDialog::AddRadioButtonGroup(int nIDRadioButtonsFirst, int nIDRadioButtonsLast)
+ // Adds a range of radio buttons to the Task Dialog.
+ // Assumes the resource ID of the button and it's string match
+ {
+ assert (m_hWnd == NULL);
+ assert(nIDRadioButtonsFirst > 0);
+ assert(nIDRadioButtonsLast > nIDRadioButtonsFirst);
+
+ TASKDIALOG_BUTTON tdb;
+ for (int nID = nIDRadioButtonsFirst; nID <= nIDRadioButtonsLast; ++nID)
+ {
+ tdb.nButtonID = nID;
+ tdb.pszButtonText = MAKEINTRESOURCEW(nID);
+ m_vRadioButtons.push_back(tdb);
+ }
+ }
+
+ inline void CTaskDialog::ClickButton(int nButtonID) const
+ // Simulates the action of a button click in the Task Dialog.
+ {
+ assert(m_hWnd);
+ SendMessage(TDM_CLICK_BUTTON, (WPARAM)nButtonID, 0);
+ }
+
+ inline void CTaskDialog::ClickRadioButton(int nRadioButtonID) const
+ // Simulates the action of a radio button click in the TaskDialog.
+ {
+ assert(m_hWnd);
+ SendMessage(TDM_CLICK_RADIO_BUTTON, (WPARAM)nRadioButtonID, 0);
+ }
+
+ inline LRESULT CTaskDialog::DoModal(CWnd* pParent /* = NULL */)
+ // Creates and displays the Task Dialog.
+ {
+ assert (m_hWnd == NULL);
+
+ m_tc.cbSize = sizeof(m_tc);
+ m_tc.pButtons = m_vButtons.empty()? NULL : &m_vButtons.front();
+ m_tc.cButtons = m_vButtons.size();
+ m_tc.pRadioButtons = m_vRadioButtons.empty()? NULL : &m_vRadioButtons.front();
+ m_tc.cRadioButtons = m_vRadioButtons.size();
+ m_tc.hwndParent = pParent? pParent->GetHwnd() : NULL;
+
+ // Ensure this thread has the TLS index set
+ TLSData* pTLSData = GetApp()->SetTlsIndex();
+
+ // Store the CWnd pointer in thread local storage
+ pTLSData->pCWnd = this;
+
+ // Declare a pointer to the TaskDialogIndirect function
+ HMODULE hComCtl = ::LoadLibrary(_T("COMCTL32.DLL"));
+ assert(hComCtl);
+ typedef HRESULT WINAPI TASKDIALOGINDIRECT(const TASKDIALOGCONFIG*, int*, int*, BOOL*);
+ TASKDIALOGINDIRECT* pTaskDialogIndirect = (TASKDIALOGINDIRECT*)::GetProcAddress(hComCtl, "TaskDialogIndirect");
+
+ // Call TaskDialogIndirect through our function pointer
+ LRESULT lr = (*pTaskDialogIndirect)(&m_tc, &m_SelectedButtonID, &m_SelectedRadioButtonID, &m_VerificationCheckboxState);
+
+ FreeLibrary(hComCtl);
+ return lr;
+ }
+
+ inline void CTaskDialog::ElevateButton(int nButtonID, BOOL bElevated)
+ // Adds a shield icon to indicate that the button's action requires elevated privilages.
+ {
+ assert(m_hWnd);
+ SendMessage(TDM_SET_BUTTON_ELEVATION_REQUIRED_STATE, (WPARAM)nButtonID, (LPARAM)bElevated);
+ }
+
+ inline void CTaskDialog::EnableButton(int nButtonID, BOOL bEnabled)
+ // Enables or disables a push button in the TaskDialog.
+ {
+ assert(m_hWnd);
+ SendMessage(TDM_ENABLE_BUTTON, (WPARAM)nButtonID, (LPARAM)bEnabled);
+ }
+ inline void CTaskDialog::EnableRadioButton(int nRadioButtonID, BOOL bEnabled)
+ // Enables or disables a radio button in the TaskDialog.
+ {
+ assert(m_hWnd);
+ SendMessage(TDM_ENABLE_RADIO_BUTTON, (WPARAM)nRadioButtonID, (LPARAM)bEnabled);
+ }
+
+ inline TASKDIALOGCONFIG CTaskDialog::GetConfig() const
+ // Returns the TASKDIALOGCONFIG structure for the Task Dialog.
+ {
+ return m_tc;
+ }
+
+ inline TASKDIALOG_FLAGS CTaskDialog::GetOptions() const
+ // Returns the Task Dialog's options. These are a combination of:
+ // TDF_ENABLE_HYPERLINKS
+ // TDF_USE_HICON_MAIN
+ // TDF_USE_HICON_FOOTER
+ // TDF_ALLOW_DIALOG_CANCELLATION
+ // TDF_USE_COMMAND_LINKS
+ // TDF_USE_COMMAND_LINKS_NO_ICON
+ // TDF_EXPAND_FOOTER_AREA
+ // TDF_EXPANDED_BY_DEFAULT
+ // TDF_VERIFICATION_FLAG_CHECKED
+ // TDF_SHOW_PROGRESS_BAR
+ // TDF_SHOW_MARQUEE_PROGRESS_BAR
+ // TDF_CALLBACK_TIMER
+ // TDF_POSITION_RELATIVE_TO_WINDOW
+ // TDF_RTL_LAYOUT
+ // TDF_NO_DEFAULT_RADIO_BUTTON
+ // TDF_CAN_BE_MINIMIZED
+ {
+ return m_tc.dwFlags;
+ }
+
+ inline int CTaskDialog::GetSelectedButtonID() const
+ // Returns the ID of the selected button.
+ {
+ assert (m_hWnd == NULL);
+ return m_SelectedButtonID;
+ }
+
+ inline int CTaskDialog::GetSelectedRadioButtonID() const
+ // Returns the ID of the selected radio button.
+ {
+ assert (m_hWnd == NULL);
+ return m_SelectedRadioButtonID;
+ }
+
+ inline BOOL CTaskDialog::GetVerificationCheckboxState() const
+ // Returns the state of the verification check box.
+ {
+ assert (m_hWnd == NULL);
+ return m_VerificationCheckboxState;
+ }
+
+ inline BOOL CTaskDialog::IsSupported()
+ // Returns true if TaskDialogs are supported on this system.
+ {
+ HMODULE hModule = ::LoadLibrary(_T("COMCTL32.DLL"));
+ assert(hModule);
+
+ BOOL bResult = (BOOL)::GetProcAddress(hModule, "TaskDialogIndirect");
+
+ ::FreeLibrary(hModule);
+ return bResult;
+ }
+
+ inline void CTaskDialog::NavigateTo(CTaskDialog& TaskDialog) const
+ // Replaces the information displayed by the task dialog.
+ {
+ assert(m_hWnd);
+ TASKDIALOGCONFIG tc = TaskDialog.GetConfig();
+ SendMessage(TDM_NAVIGATE_PAGE, 0, (LPARAM)&tc);
+ }
+
+ inline BOOL CTaskDialog::OnTDButtonClicked(int nButtonID)
+ // Called when the user selects a button or command link.
+ {
+ UNREFERENCED_PARAMETER(nButtonID);
+
+ // return TRUE to prevent the task dialog from closing
+ return FALSE;
+ }
+
+ inline void CTaskDialog::OnTDConstructed()
+ // Called when the task dialog is constructed, before it is displayed.
+ {}
+
+ inline void CTaskDialog::OnTDCreated()
+ // Called when the task dialog is displayed.
+ {}
+
+ inline void CTaskDialog::OnTDDestroyed()
+ // Called when the task dialog is destroyed.
+ {
+ }
+
+ inline void CTaskDialog::OnTDExpandButtonClicked(BOOL bExpanded)
+ // Called when the expand button is clicked.
+ {
+ UNREFERENCED_PARAMETER(bExpanded);
+ }
+
+ inline void CTaskDialog::OnTDHelp()
+ // Called when the user presses F1 on the keyboard.
+ {}
+
+ inline void CTaskDialog::OnTDHyperlinkClicked(LPCTSTR pszHref)
+ // Called when the user clicks on a hyperlink.
+ {
+ UNREFERENCED_PARAMETER(pszHref);
+ }
+
+ inline void CTaskDialog::OnTDNavigatePage()
+ // Called when a navigation has occurred.
+ {}
+
+ inline BOOL CTaskDialog::OnTDRadioButtonClicked(int nRadioButtonID)
+ // Called when the user selects a radio button.
+ {
+ UNREFERENCED_PARAMETER(nRadioButtonID);
+ return TRUE;
+ }
+
+ inline BOOL CTaskDialog::OnTDTimer(DWORD dwTickCount)
+ // Called every 200 milliseconds (aproximately) when the TDF_CALLBACK_TIMER flag is set.
+ {
+ UNREFERENCED_PARAMETER(dwTickCount);
+
+ // return TRUE to reset the tick count
+ return FALSE;
+ }
+
+ inline void CTaskDialog::OnTDVerificationCheckboxClicked(BOOL bChecked)
+ // Called when the user clicks the Task Dialog verification check box.
+ {
+ UNREFERENCED_PARAMETER(bChecked);
+ }
+
+ inline void CTaskDialog::RemoveAllButtons()
+ // Removes all push buttons from the task dialog.
+ {
+ assert (m_hWnd == NULL);
+ m_vButtons.clear();
+ m_vButtonsText.clear();
+ }
+
+ inline void CTaskDialog::RemoveAllRadioButtons()
+ // Removes all radio buttons from the task dialog.
+ {
+ assert (m_hWnd == NULL);
+ m_vRadioButtons.clear();
+ m_vRadioButtonsText.clear();
+ }
+
+ inline void CTaskDialog::Reset()
+ // Returns the dialog to its default state.
+ {
+ assert (m_hWnd == NULL);
+
+ RemoveAllButtons();
+ RemoveAllRadioButtons();
+ ZeroMemory(&m_tc, sizeof(m_tc));
+ m_tc.cbSize = sizeof(m_tc);
+ m_tc.pfCallback = CTaskDialog::StaticTaskDialogProc;
+
+ m_SelectedButtonID = 0;
+ m_SelectedRadioButtonID = 0;
+ m_VerificationCheckboxState = FALSE;
+
+ m_vWindowTitle.clear();
+ m_vMainInstruction.clear();
+ m_vContent.clear();
+ m_vVerificationText.clear();
+ m_vExpandedInformation.clear();
+ m_vExpandedControlText.clear();
+ m_vCollapsedControlText.clear();
+ m_vFooter.clear();
+ }
+
+ inline void CTaskDialog::SetCommonButtons(TASKDIALOG_COMMON_BUTTON_FLAGS dwCommonButtons)
+ // The dwCommonButtons parameter can be a combination of:
+ // TDCBF_OK_BUTTON OK button
+ // TDCBF_YES_BUTTON Yes button
+ // TDCBF_NO_BUTTON No button
+ // TDCBF_CANCEL_BUTTON Cancel button
+ // TDCBF_RETRY_BUTTON Retry button
+ // TDCBF_CLOSE_BUTTON Close button
+ {
+ assert (m_hWnd == NULL);
+ m_tc.dwCommonButtons = dwCommonButtons;
+ }
+
+ inline void CTaskDialog::SetContent(LPCTSTR pszContent)
+ // Sets the task dialog's primary content.
+ {
+ StoreText(m_vContent, pszContent);
+ m_tc.pszContent = &m_vContent.front();
+
+ if (IsWindow())
+ SendMessage(TDM_SET_ELEMENT_TEXT, (WPARAM)TDE_CONTENT, (LPARAM)(LPCWSTR)T2W(pszContent));
+ }
+
+ inline void CTaskDialog::SetDefaultButton(int nButtonID)
+ // Sets the task dialog's default button.
+ // Can be either a button ID or one of the common buttons
+ {
+ assert (m_hWnd == NULL);
+ m_tc.nDefaultButton = nButtonID;
+ }
+
+ inline void CTaskDialog::SetDefaultRadioButton(int nRadioButtonID)
+ // Sets the default radio button.
+ {
+ assert (m_hWnd == NULL);
+ m_tc.nDefaultRadioButton = nRadioButtonID;
+ }
+
+ inline void CTaskDialog::SetDialogWidth(UINT nWidth /*= 0*/)
+ // The width of the task dialog's client area. If 0, the
+ // task dialog manager will calculate the ideal width.
+ {
+ assert (m_hWnd == NULL);
+ m_tc.cxWidth = nWidth;
+ }
+
+ inline void CTaskDialog::SetExpansionArea(LPCTSTR pszExpandedInfo, LPCTSTR pszExpandedLabel /* = _T("")*/, LPCTSTR pszCollapsedLabel /* = _T("")*/)
+ // Sets the text in the expandable area of the Task Dialog.
+ {
+ StoreText(m_vExpandedInformation, pszExpandedInfo);
+ m_tc.pszExpandedInformation = &m_vExpandedInformation.front();
+
+ StoreText(m_vExpandedControlText, pszExpandedLabel);
+ m_tc.pszExpandedControlText = &m_vExpandedControlText.front();
+
+ StoreText(m_vCollapsedControlText, pszCollapsedLabel);
+ m_tc.pszCollapsedControlText = &m_vCollapsedControlText.front();
+
+ if (IsWindow())
+ SendMessage(TDM_SET_ELEMENT_TEXT, (WPARAM)TDE_EXPANDED_INFORMATION, (LPARAM)(LPCWSTR)T2W(pszExpandedInfo));
+ }
+
+ inline void CTaskDialog::SetFooterIcon(HICON hFooterIcon)
+ // Sets the icon that will be displayed in the Task Dialog's footer.
+ {
+ m_tc.hFooterIcon = hFooterIcon;
+
+ if (IsWindow())
+ SendMessage(TDM_UPDATE_ICON, (WPARAM)TDIE_ICON_FOOTER, (LPARAM)hFooterIcon);
+ }
+
+ inline void CTaskDialog::SetFooterIcon(LPCTSTR lpszFooterIcon)
+ // Sets the icon that will be displayed in the Task Dialog's footer.
+ // Possible icons:
+ // TD_ERROR_ICON A stop-sign icon appears in the task dialog.
+ // TD_WARNING_ICON An exclamation-point icon appears in the task dialog.
+ // TD_INFORMATION_ICON An icon consisting of a lowercase letter i in a circle appears in the task dialog.
+ // TD_SHIELD_ICON A shield icon appears in the task dialog.
+ // or a value passed via MAKEINTRESOURCE
+ {
+ m_tc.pszFooterIcon = (LPCWSTR)lpszFooterIcon;
+
+ if (IsWindow())
+ SendMessage(TDM_UPDATE_ICON, (WPARAM)TDIE_ICON_FOOTER, (LPARAM)lpszFooterIcon);
+ }
+
+ inline void CTaskDialog::SetFooterText(LPCTSTR pszFooter)
+ // Sets the text that will be displayed in the Task Dialog's footer.
+ {
+ StoreText(m_vFooter, pszFooter);
+ m_tc.pszFooter = &m_vFooter.front();
+
+ if (IsWindow())
+ SendMessage(TDM_SET_ELEMENT_TEXT, (WPARAM)TDE_FOOTER, (LPARAM)(LPCWSTR)T2W(pszFooter));
+ }
+
+ inline void CTaskDialog::SetMainIcon(HICON hMainIcon)
+ // Sets Task Dialog's main icon.
+ {
+ m_tc.hMainIcon = hMainIcon;
+
+ if (IsWindow())
+ SendMessage(TDM_UPDATE_ICON, (WPARAM)TDIE_ICON_MAIN, (LPARAM)hMainIcon);
+ }
+
+ inline void CTaskDialog::SetMainIcon(LPCTSTR lpszMainIcon)
+ // Sets Task Dialog's main icon.
+ // Possible icons:
+ // TD_ERROR_ICON A stop-sign icon appears in the task dialog.
+ // TD_WARNING_ICON An exclamation-point icon appears in the task dialog.
+ // TD_INFORMATION_ICON An icon consisting of a lowercase letter i in a circle appears in the task dialog.
+ // TD_SHIELD_ICON A shield icon appears in the task dialog.
+ // or a value passed via MAKEINTRESOURCE
+ //
+ // Note: Some values of main icon will also generate a MessageBeep when the TaskDialog is created.
+ {
+ m_tc.pszMainIcon = (LPCWSTR)lpszMainIcon;
+
+ if (IsWindow())
+ SendMessage(TDM_UPDATE_ICON, (WPARAM)TDIE_ICON_MAIN, (LPARAM)lpszMainIcon);
+ }
+
+ inline void CTaskDialog::SetMainInstruction(LPCTSTR pszMainInstruction)
+ // Sets the Task Dialog's main instruction text.
+ {
+ StoreText(m_vMainInstruction, pszMainInstruction);
+ m_tc.pszMainInstruction = &m_vMainInstruction.front();
+
+ if (IsWindow())
+ SendMessage(TDM_SET_ELEMENT_TEXT, (WPARAM)TDE_FOOTER, (LPARAM)(LPCWSTR)T2W(pszMainInstruction));
+ }
+
+ inline void CTaskDialog::SetOptions(TASKDIALOG_FLAGS dwFlags)
+ // Sets the Task Dialog's options. These are a combination of:
+ // TDF_ENABLE_HYPERLINKS
+ // TDF_USE_HICON_MAIN
+ // TDF_USE_HICON_FOOTER
+ // TDF_ALLOW_DIALOG_CANCELLATION
+ // TDF_USE_COMMAND_LINKS
+ // TDF_USE_COMMAND_LINKS_NO_ICON
+ // TDF_EXPAND_FOOTER_AREA
+ // TDF_EXPANDED_BY_DEFAULT
+ // TDF_VERIFICATION_FLAG_CHECKED
+ // TDF_SHOW_PROGRESS_BAR
+ // TDF_SHOW_MARQUEE_PROGRESS_BAR
+ // TDF_CALLBACK_TIMER
+ // TDF_POSITION_RELATIVE_TO_WINDOW
+ // TDF_RTL_LAYOUT
+ // TDF_NO_DEFAULT_RADIO_BUTTON
+ // TDF_CAN_BE_MINIMIZED
+ {
+ assert (m_hWnd == NULL);
+ m_tc.dwFlags = dwFlags;
+ }
+
+ inline void CTaskDialog::SetProgressBarMarquee(BOOL bEnabled /* = TRUE*/, int nMarqueeSpeed /* = 0*/)
+ // Starts and stops the marquee display of the progress bar, and sets the speed of the marquee.
+ {
+ assert(m_hWnd);
+ SendMessage(TDM_SET_PROGRESS_BAR_MARQUEE, (WPARAM)bEnabled, (LPARAM)nMarqueeSpeed);
+ }
+
+ inline void CTaskDialog::SetProgressBarPosition(int nProgressPos)
+ // Sets the current position for a progress bar.
+ {
+ assert(m_hWnd);
+ SendMessage(TDM_SET_PROGRESS_BAR_POS, (WPARAM)nProgressPos, 0);
+ }
+
+ inline void CTaskDialog::SetProgressBarRange(int nMinRange, int nMaxRange)
+ // Sets the minimum and maximum values for the hosted progress bar.
+ {
+ assert(m_hWnd);
+ SendMessage(TDM_SET_PROGRESS_BAR_RANGE, 0, MAKELPARAM(nMinRange, nMaxRange));
+ }
+
+ inline void CTaskDialog::SetProgressBarState(int nNewState /* = PBST_NORMAL*/)
+ // Sets the current state of the progress bar. Possible states are:
+ // PBST_NORMAL
+ // PBST_PAUSE
+ // PBST_ERROR
+ {
+ assert(m_hWnd);
+ SendMessage(TDM_SET_PROGRESS_BAR_STATE, (WPARAM)nNewState, 0);
+ }
+
+ inline void CTaskDialog::SetVerificationCheckbox(BOOL bChecked)
+ // Simulates a click on the verification checkbox of the Task Dialog, if it exists.
+ {
+ assert(m_hWnd);
+ SendMessage(TDM_CLICK_VERIFICATION, (WPARAM)bChecked, (LPARAM)bChecked);
+ }
+
+ inline void CTaskDialog::SetVerificationCheckboxText(LPCTSTR pszVerificationText)
+ // Sets the text for the verification check box.
+ {
+ assert (m_hWnd == NULL);
+ StoreText(m_vVerificationText, pszVerificationText);
+ m_tc.pszVerificationText = &m_vVerificationText.front();
+ }
+
+ inline void CTaskDialog::SetWindowTitle(LPCTSTR pszWindowTitle)
+ // Sets the Task Dialog's window title.
+ {
+ assert (m_hWnd == NULL);
+ StoreText(m_vWindowTitle, pszWindowTitle);
+ m_tc.pszWindowTitle = &m_vWindowTitle.front();
+ }
+
+ inline HRESULT CALLBACK CTaskDialog::StaticTaskDialogProc(HWND hWnd, UINT uNotification, WPARAM wParam, LPARAM lParam, LONG_PTR dwRefData)
+ // TaskDialogs direct their messages here.
+ {
+ UNREFERENCED_PARAMETER(dwRefData);
+
+ assert( GetApp() );
+
+ try
+ {
+ CTaskDialog* t = (CTaskDialog*)GetApp()->GetCWndFromMap(hWnd);
+ if (0 == t)
+ {
+ // The CTaskDialog pointer wasn't found in the map, so add it now
+
+ // Retrieve the pointer to the TLS Data
+ TLSData* pTLSData = (TLSData*)TlsGetValue(GetApp()->GetTlsIndex());
+ if (NULL == pTLSData)
+ throw CWinException(_T("Unable to get TLS"));
+
+ // Retrieve pointer to CTaskDialog object from Thread Local Storage TLS
+ t = (CTaskDialog*)(pTLSData->pCWnd);
+ if (NULL == t)
+ throw CWinException(_T("Failed to route message"));
+
+ pTLSData->pCWnd = NULL;
+
+ // Store the CTaskDialog pointer in the HWND map
+ t->m_hWnd = hWnd;
+ t->AddToMap();
+ }
+
+ return t->TaskDialogProc(uNotification, wParam, lParam);
+ }
+
+ catch (const CWinException &e)
+ {
+ // Most CWinExceptions will end up here unless caught earlier.
+ e.what();
+ }
+
+ return 0L;
+
+ } // LRESULT CALLBACK StaticTaskDialogProc(...)
+
+ inline void CTaskDialog::StoreText(std::vector<WCHAR>& vWChar, LPCTSTR pFromTChar)
+ {
+ // Stores a TChar string in a WCHAR vector
+
+ std::vector<TCHAR> vTChar;
+
+ if (IS_INTRESOURCE(pFromTChar)) // support MAKEINTRESOURCE
+ {
+ tString ts = LoadString((UINT)pFromTChar);
+ int len = pFromTChar? ts.length() + 1 : 1;
+ vTChar.assign(len, _T('\0'));
+ vWChar.assign(len, _T('\0'));
+ if (pFromTChar)
+ lstrcpy( &vTChar.front(), ts.c_str());
+
+ }
+ else
+ {
+ int len = lstrlen(pFromTChar) +1;
+ vTChar.assign(len, _T('\0'));
+ vWChar.assign(len, _T('\0'));
+ lstrcpy( &vTChar.front(), pFromTChar);
+ }
+
+ lstrcpyW(&vWChar.front(), T2W(&vTChar.front()) );
+ }
+
+ inline LRESULT CTaskDialog::TaskDialogProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam)
+ // Handles the Task Dialog's notificaions.
+ {
+ switch(uMsg)
+ {
+ case TDN_BUTTON_CLICKED:
+ return OnTDButtonClicked((int)wParam);
+
+ case TDN_CREATED:
+ OnTDCreated();
+ break;
+ case TDN_DESTROYED:
+ Cleanup(); // Prepare this CWnd to be reused.
+ OnTDDestroyed();
+ break;
+ case TDN_DIALOG_CONSTRUCTED:
+ OnTDConstructed();
+ break;
+ case TDN_EXPANDO_BUTTON_CLICKED:
+ OnTDExpandButtonClicked((BOOL)wParam);
+ break;
+ case TDN_HELP:
+ OnTDHelp();
+ break;
+ case TDN_HYPERLINK_CLICKED:
+ OnTDHyperlinkClicked(W2T((LPCWSTR)lParam));
+ break;
+ case TDN_NAVIGATED:
+ OnTDNavigatePage();
+ break;
+ case TDN_RADIO_BUTTON_CLICKED:
+ OnTDRadioButtonClicked((int)wParam);
+ break;
+ case TDN_TIMER:
+ return OnTDTimer((DWORD)wParam);
+
+ case TDN_VERIFICATION_CLICKED:
+ OnTDVerificationCheckboxClicked((BOOL)wParam);
+ break;
+ }
+
+ return S_OK;
+ }
+
+ inline LRESULT CTaskDialog::TaskDialogProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
+ {
+ // Override this function in your class derrived from CDialog if you wish to handle messages
+ // A typical function might look like this:
+
+ // switch (uMsg)
+ // {
+ // case MESSAGE1: // Some Windows API message
+ // OnMessage1(); // A user defined function
+ // break; // Also do default processing
+ // case MESSAGE2:
+ // OnMessage2();
+ // return x; // Don't do default processing, but instead return
+ // // a value recommended by the Windows API documentation
+ // }
+
+ // Always pass unhandled messages on to TaskDialogProcDefault
+ return TaskDialogProcDefault(uMsg, wParam, lParam);
+ }
+
+ inline void CTaskDialog::UpdateElementText(TASKDIALOG_ELEMENTS eElement, LPCTSTR pszNewText)
+ // Updates a text element on the Task Dialog.
+ {
+ assert(m_hWnd);
+ SendMessage(TDM_UPDATE_ELEMENT_TEXT, (WPARAM)eElement, (LPARAM)(LPCWSTR)T2W(pszNewText));
+ }
+
+}
+
+
+
+#endif // _WIN32XX_TASKDIALOG_H_ \ No newline at end of file
diff --git a/mmc_updater/depends/win32cpp/thread.h b/mmc_updater/depends/win32cpp/thread.h
new file mode 100644
index 00000000..5564d888
--- /dev/null
+++ b/mmc_updater/depends/win32cpp/thread.h
@@ -0,0 +1,241 @@
+// Win32++ Version 7.2
+// Released: 5th AUgust 2011
+//
+// David Nash
+// email: dnash@bigpond.net.au
+// url: https://sourceforge.net/projects/win32-framework
+//
+//
+// Copyright (c) 2005-2011 David Nash
+//
+// Permission is hereby granted, free of charge, to
+// any person obtaining a copy of this software and
+// associated documentation files (the "Software"),
+// to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify,
+// merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom
+// the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice
+// shall be included in all copies or substantial portions
+// of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
+// OR OTHER DEALINGS IN THE SOFTWARE.
+//
+////////////////////////////////////////////////////////
+
+
+// The CThread class simplifies the use of threads with Win32++.
+// To use threads in your Win32++ application, inherit a class from
+// CThread, and override InitInstance. When your class is instanciated,
+// a new thread is started, and the InitInstance function is called to
+// run in the new thread.
+
+// If your thread is used to run one or more windows, InitInstance should
+// return TRUE, causing the MessageLoop function to be called. If your
+// thread doesn't require a MessageLoop, it should return FALSE. Threads
+// which don't run a message loop as sometimes referred to as "worker" threads.
+
+// Note: It is your job to end the thread before CThread ends!
+// To end a thread with a message loop, use PostQuitMessage on the thread.
+// To end a thread without a message loop, set an event, and end the thread
+// when the event is received.
+
+// Hint: It is never a good idea to use things like TerminateThread or ExitThread to
+// end your thread. These represent poor programming techniques, and are likely
+// to leak memory and resources.
+
+// More Hints for thread programming:
+// 1) Avoid using SendMessage between threads, as this will cause one thread to wait for
+// the other to respond. Use PostMessage between threads to avoid this problem.
+// 2) Access to variables and resources shared between threads need to be made thread safe.
+// Having one thread modify a resouce or variable while another thread is accessing it is
+// a recipe for disaster.
+// 3) Thread Local Storage (TLS) can be used to replace global variables to make them thread
+// safe. With TLS, each thread gets its own copy of the variable.
+// 4) Critical Sections can be used to make shared resources thread safe.
+// 5) Window messages (including user defined messages) can be posted between GUI threads to
+// communicate information between them.
+// 6) Events (created by CreateEvent) can be used to comunicate information between threads
+// (both GUI and worker threads).
+// 7) Avoid using sleep to synchronise threads. Generally speaking, the various wait
+// functions (e.g. WaitForSingleObject) will be better for this.
+
+// About Threads:
+// Each program that executes has a "process" allocated to it. A process has one or more
+// threads. Threads run independantly of each other. It is the job of the operating system
+// to manage the running of the threads, and do the task switching between threads as required.
+// Systems with multiple CPUs will be able to run as many threads simultaneously as there are
+// CPUs.
+
+// Threads behave like a program within a program. When the main thread starts, the application
+// runs the WinMain function and ends when WinMain ends. When another thread starts, it too
+// will run the function provided to it, and end when that function ends.
+
+
+#ifndef _WIN32XX_WINTHREAD_H_
+#define _WIN32XX_WINTHREAD_H_
+
+
+#include <process.h>
+
+
+namespace Win32xx
+{
+
+ //////////////////////////////////////
+ // Declaration of the CThread class
+ //
+ class CThread
+ {
+ public:
+ CThread();
+ CThread(LPSECURITY_ATTRIBUTES pSecurityAttributes, unsigned stack_size, unsigned initflag);
+ virtual ~CThread();
+
+ // Overridables
+ virtual BOOL InitInstance();
+ virtual int MessageLoop();
+
+ // Operations
+ HANDLE GetThread() const;
+ int GetThreadID() const;
+ int GetThreadPriority() const;
+ DWORD ResumeThread() const;
+ BOOL SetThreadPriority(int nPriority) const;
+ DWORD SuspendThread() const;
+
+ private:
+ CThread(const CThread&); // Disable copy construction
+ CThread& operator = (const CThread&); // Disable assignment operator
+ void CreateThread(LPSECURITY_ATTRIBUTES pSecurityAttributes, unsigned stack_size, unsigned initflag);
+ static UINT WINAPI StaticThreadCallback(LPVOID pCThread);
+
+ HANDLE m_hThread; // Handle of this thread
+ UINT m_nThreadID; // ID of this thread
+ };
+
+}
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+namespace Win32xx
+{
+
+ ///////////////////////////////////////
+ // Definitions for the CThread class
+ //
+ inline CThread::CThread() : m_hThread(0), m_nThreadID(0)
+ {
+ CreateThread(0, 0, CREATE_SUSPENDED);
+ }
+
+ inline CThread::CThread(LPSECURITY_ATTRIBUTES pSecurityAttributes, unsigned stack_size, unsigned initflag)
+ : m_hThread(0), m_nThreadID(0)
+
+ {
+ // Valid argument values:
+ // pSecurityAttributes Either a pointer to SECURITY_ATTRIBUTES or 0
+ // stack_size Either the stack size or 0
+ // initflag Either CREATE_SUSPENDED or 0
+
+ CreateThread(pSecurityAttributes, stack_size, initflag);
+ }
+
+ inline CThread::~CThread()
+ {
+ // A thread's state is set to signalled when the thread terminates.
+ // If your thread is still running at this point, you have a bug.
+ if (0 != WaitForSingleObject(m_hThread, 0))
+ TRACE(_T("*** Error *** Ending CThread before ending its thread\n"));
+
+ // Close the thread's handle
+ ::CloseHandle(m_hThread);
+ }
+
+ inline void CThread::CreateThread(LPSECURITY_ATTRIBUTES pSecurityAttributes, unsigned stack_size, unsigned initflag)
+ {
+ // NOTE: By default, the thread is created in the default state.
+ m_hThread = (HANDLE)_beginthreadex(pSecurityAttributes, stack_size, CThread::StaticThreadCallback, (LPVOID) this, initflag, &m_nThreadID);
+
+ if (0 == m_hThread)
+ throw CWinException(_T("Failed to create thread"));
+ }
+
+ inline HANDLE CThread::GetThread() const
+ {
+ assert(m_hThread);
+ return m_hThread;
+ }
+
+ inline int CThread::GetThreadID() const
+ {
+ assert(m_hThread);
+ return m_nThreadID;
+ }
+
+ inline int CThread::GetThreadPriority() const
+ {
+ assert(m_hThread);
+ return ::GetThreadPriority(m_hThread);
+ }
+
+ inline BOOL CThread::InitInstance()
+ {
+ // Override this function to perform tasks when the thread starts.
+
+ // return TRUE to run a message loop, otherwise return FALSE.
+ // A thread with a window must run a message loop.
+ return FALSE;
+ }
+
+ inline int CThread::MessageLoop()
+ {
+ // Override this function if your thread needs a different message loop
+ return GetApp()->MessageLoop();
+ }
+
+ inline DWORD CThread::ResumeThread() const
+ {
+ assert(m_hThread);
+ return ::ResumeThread(m_hThread);
+ }
+
+ inline DWORD CThread::SuspendThread() const
+ {
+ assert(m_hThread);
+ return ::SuspendThread(m_hThread);
+ }
+
+ inline BOOL CThread::SetThreadPriority(int nPriority) const
+ {
+ assert(m_hThread);
+ return ::SetThreadPriority(m_hThread, nPriority);
+ }
+
+ inline UINT WINAPI CThread::StaticThreadCallback(LPVOID pCThread)
+ // When the thread starts, it runs this function.
+ {
+ // Get the pointer for this CMyThread object
+ CThread* pThread = (CThread*)pCThread;
+
+ if (pThread->InitInstance())
+ return pThread->MessageLoop();
+
+ return 0;
+ }
+
+}
+
+#endif // #define _WIN32XX_WINTHREAD_H_
+
diff --git a/mmc_updater/depends/win32cpp/toolbar.h b/mmc_updater/depends/win32cpp/toolbar.h
new file mode 100644
index 00000000..1ed005a0
--- /dev/null
+++ b/mmc_updater/depends/win32cpp/toolbar.h
@@ -0,0 +1,1361 @@
+// Win32++ Version 7.2
+// Released: 5th AUgust 2011
+//
+// David Nash
+// email: dnash@bigpond.net.au
+// url: https://sourceforge.net/projects/win32-framework
+//
+//
+// Copyright (c) 2005-2011 David Nash
+//
+// Permission is hereby granted, free of charge, to
+// any person obtaining a copy of this software and
+// associated documentation files (the "Software"),
+// to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify,
+// merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom
+// the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice
+// shall be included in all copies or substantial portions
+// of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
+// OR OTHER DEALINGS IN THE SOFTWARE.
+//
+////////////////////////////////////////////////////////
+
+
+#ifndef _WIN32XX_TOOLBAR_H_
+#define _WIN32XX_TOOLBAR_H_
+
+#include "wincore.h"
+#include "gdi.h"
+#include "rebar.h"
+
+
+namespace Win32xx
+{
+
+ struct ToolBarTheme
+ {
+ BOOL UseThemes; // TRUE if themes are used
+ COLORREF clrHot1; // Colour 1 for hot button
+ COLORREF clrHot2; // Colour 2 for hot button
+ COLORREF clrPressed1; // Colour 1 for pressed button
+ COLORREF clrPressed2; // Colour 2 for pressed button
+ COLORREF clrOutline; // Colour for border outline
+ };
+
+
+ ////////////////////////////////////
+ // Declaration of the CToolBar class
+ //
+ class CToolBar : public CWnd
+ {
+ public:
+ CToolBar();
+ virtual ~CToolBar();
+
+ // Operations
+ virtual int AddBitmap(UINT ToolBarID);
+ virtual BOOL AddButton(UINT nID, BOOL bEnabled = TRUE);
+ virtual void Destroy();
+ virtual BOOL ReplaceBitmap(UINT NewToolBarID);
+ virtual BOOL SetBitmap(UINT nID);
+ virtual int SetButtons(const std::vector<UINT>& vToolBarData) const;
+ virtual BOOL SetButtonText(int idButton, LPCTSTR szText);
+ virtual BOOL SetImages(COLORREF crMask, UINT ToolBarID, UINT ToolBarHotID, UINT ToolBarDisabledID);
+
+ // Wrappers for Win32 API functions
+ BOOL AddButtons(UINT uNumButtons, LPTBBUTTON lpButtons) const;
+ int AddString(UINT nStringID) const;
+ int AddStrings(LPCTSTR lpszStrings) const;
+ void Autosize() const;
+ void CheckButton(int idButton, BOOL fCheck) const;
+ int CommandToIndex(int idButton) const;
+ BOOL DeleteButton(int iButton) const;
+ BOOL DisableButton(int idButton) const;
+ BOOL EnableButton(int idButton) const;
+ BOOL GetButton(int iButton, LPTBBUTTON lpButton) const;
+ int GetButtonCount() const;
+ DWORD GetButtonSize() const;
+ UINT GetButtonState(int idButton) const;
+ BYTE GetButtonStyle(int idButton) const;
+ CString GetButtonText(int idButton) const;
+ int GetCommandID(int iIndex) const;
+ HIMAGELIST GetDisabledImageList() const;
+ int GetHotItem() const;
+ HIMAGELIST GetHotImageList() const;
+ HIMAGELIST GetImageList() const;
+ CRect GetItemRect(int iIndex) const;
+ CSize GetMaxSize() const;
+ DWORD GetPadding() const;
+ CRect GetRect(int idButton) const;
+ int GetRows() const;
+ int GetTextRows() const;
+ HWND GetToolTips() const;
+ BOOL HasText() const;
+ BOOL HideButton(int idButton, BOOL fShow) const;
+ int HitTest() const;
+ BOOL Indeterminate(int idButton, BOOL fIndeterminate) const;
+ BOOL InsertButton(int iButton, LPTBBUTTON lpButton) const;
+ BOOL IsButtonHidden(int idButton) const;
+ BOOL IsButtonHighlighted(int idButton) const;
+ BOOL IsButtonIndeterminate(int idButton) const;
+ BOOL IsButtonPressed(int idButton) const;
+ int MapAccelerator(TCHAR chAccel) const;
+ BOOL MarkButton(int idButton) const;
+ BOOL MoveButton(UINT uOldPos, UINT uNewPos) const;
+ BOOL PressButton(int idButton, BOOL fPress) const;
+ void SaveRestore(BOOL fSave, TBSAVEPARAMS* ptbsp) const;
+ BOOL SetBitmapSize(int cx, int cy) const;
+ BOOL SetButtonSize(int cx, int cy) const;
+ BOOL SetButtonState(int idButton, UINT State) const;
+ BOOL SetButtonStyle(int idButton, BYTE Style) const;
+ BOOL SetButtonWidth(int idButton, int nWidth) const;
+ BOOL SetCommandID(int iIndex, int idButton) const;
+ HIMAGELIST SetDisableImageList(HIMAGELIST himlNewDisabled) const;
+ DWORD SetDrawTextFlags(DWORD dwMask, DWORD dwDTFlags) const;
+ DWORD SetExtendedStyle(DWORD dwExStyle) const;
+ HIMAGELIST SetHotImageList(HIMAGELIST himlNewHot) const;
+ int SetHotItem(int iHot) const;
+ HIMAGELIST SetImageList(HIMAGELIST himlNew) const;
+ BOOL SetIndent(int iIndent) const;
+ BOOL SetMaxTextRows(int iMaxRows) const;
+ BOOL SetPadding(int cx, int cy) const;
+ void SetToolTips(HWND hwndToolTip) const;
+
+ // Attributes
+ std::vector<UINT>& GetToolBarData() const {return (std::vector <UINT> &)m_vToolBarData;}
+ ToolBarTheme& GetToolBarTheme() {return m_Theme;}
+ void SetToolBarTheme(ToolBarTheme& Theme);
+
+ protected:
+ // Overridables
+ virtual void OnCreate();
+ virtual void OnDestroy();
+ virtual void OnWindowPosChanging(WPARAM wParam, LPARAM lParam);
+ virtual LRESULT OnCustomDraw(NMHDR* pNMHDR);
+ virtual LRESULT OnNotifyReflect(WPARAM wParam, LPARAM lParam);
+ virtual void PreCreate(CREATESTRUCT &cs);
+ virtual void PreRegisterClass(WNDCLASS &wc);
+ virtual LRESULT WndProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam);
+
+ private:
+ CToolBar(const CToolBar&); // Disable copy construction
+ CToolBar& operator = (const CToolBar&); // Disable assignment operator
+
+ std::vector<UINT> m_vToolBarData; // vector of resource IDs for toolbar buttons
+ std::map<tString, int> m_StringMap; // a map of strings used in SetButtonText
+ UINT m_OldToolBarID; // Bitmap Resource ID, used in AddBitmap/ReplaceBitmap
+ ToolBarTheme m_Theme; // The theme structure
+ BOOL m_bDrawArrowBkgrnd; // True if a seperate arrow background is to be drawn
+
+ }; // class CToolBar
+
+}
+
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+namespace Win32xx
+{
+
+ ////////////////////////////////////
+ // Definitions for the CToolBar class
+ //
+ inline CToolBar::CToolBar() : m_OldToolBarID(0), m_bDrawArrowBkgrnd(FALSE)
+ {
+ ZeroMemory(&m_Theme, sizeof(ToolBarTheme));
+ }
+
+ inline CToolBar::~CToolBar()
+ {
+ }
+
+ inline int CToolBar::AddBitmap(UINT ToolBarID)
+ // Adds one or more images to the list of button images available for a toolbar.
+
+ // Note: AddBitmap supports a maximum colour depth of 8 bits (256 colours)
+ // For more colours, use an ImageList instead
+ {
+ assert(::IsWindow(m_hWnd));
+
+ int iNumButtons = 0;
+ std::vector<UINT>::iterator iter;
+ for (iter = GetToolBarData().begin(); iter < GetToolBarData().end(); ++iter)
+ if ((*iter) != 0) ++iNumButtons;
+
+ TBADDBITMAP tbab = {0};
+ tbab.hInst = GetApp()->GetResourceHandle();
+ tbab.nID = ToolBarID;
+ int iResult = (int)SendMessage(TB_ADDBITMAP, iNumButtons, (LPARAM)&tbab);
+
+ if (-1 != iResult)
+ m_OldToolBarID = ToolBarID;
+
+ return iResult;
+ }
+
+ inline BOOL CToolBar::AddButton(UINT nID, BOOL bEnabled /* = TRUE */)
+ // Adds Resource IDs to toolbar buttons.
+ // A resource ID of 0 is a separator
+ {
+ assert(::IsWindow(m_hWnd));
+
+ m_vToolBarData.push_back(nID);
+
+ // TBBUTTON structure for each button in the toolbar
+ TBBUTTON tbb = {0};
+
+ std::vector<UINT>::iterator iter;
+ int iImages = 0;
+ for(iter = m_vToolBarData.begin(); iter < m_vToolBarData.end(); ++iter)
+ if (0 != *iter) iImages++;
+
+ ZeroMemory(&tbb, sizeof(TBBUTTON));
+
+ if (0 == nID)
+ {
+ tbb.fsStyle = TBSTYLE_SEP;
+ }
+ else
+ {
+ tbb.dwData = iImages -1;
+ tbb.iBitmap = iImages -1;
+ tbb.idCommand = nID;
+ tbb.fsState = bEnabled? TBSTATE_ENABLED : 0;
+ tbb.fsStyle = TBSTYLE_BUTTON;
+ }
+
+ // Add the button to the toolbar
+ return (BOOL)SendMessage(TB_ADDBUTTONS, 1L, (LPARAM)&tbb);
+ }
+
+ inline BOOL CToolBar::AddButtons(UINT uNumButtons, LPTBBUTTON lpButtons) const
+ // Adds one or more buttons to a toolbar.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (BOOL)SendMessage(TB_ADDBUTTONS, (LPARAM)uNumButtons, (WPARAM)lpButtons);
+ }
+
+ inline int CToolBar::AddString(UINT nStringID) const
+ // Adds a new string, passed as a resource ID, to the toolbar's internal list of strings.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (int)SendMessage(TB_ADDSTRING, (LPARAM)GetApp()->GetResourceHandle(), (WPARAM)nStringID);
+ }
+
+ inline int CToolBar::AddStrings(LPCTSTR lpszStrings) const
+ // Adds a new string or strings to the list of strings available for a toolbar control.
+ // Strings in the buffer must be separated by a null character. You must ensure that the last string has two null terminators.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (int)SendMessage(TB_ADDSTRING, 0L, (WPARAM)lpszStrings);
+ }
+
+ inline void CToolBar::Autosize() const
+ // Causes a toolbar to be resized.
+ {
+ assert(::IsWindow(m_hWnd));
+ SendMessage(TB_AUTOSIZE, 0L, 0L);
+ }
+
+ inline void CToolBar::CheckButton(int idButton, BOOL fCheck) const
+ // Checks or unchecks a given button in a toolbar.
+ // When a button is checked, it is displayed in the pressed state.
+ {
+ assert(::IsWindow(m_hWnd));
+ SendMessage(TB_CHECKBUTTON, (WPARAM)idButton, (LPARAM)MAKELONG(fCheck, 0));
+ }
+
+ inline int CToolBar::CommandToIndex(int idButton) const
+ // Retrieves the zero-based index for the button associated with the specified command identifier
+ {
+ assert(::IsWindow(m_hWnd));
+
+ // returns -1 on fail
+ return (int)SendMessage(TB_COMMANDTOINDEX, (WPARAM)idButton, 0L);
+ }
+
+ inline BOOL CToolBar::DeleteButton(int iButton) const
+ // Deletes a button from the toolbar.
+ // iButton is the Zero-based index of the button to delete.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (int)SendMessage(TB_DELETEBUTTON, (WPARAM)iButton, 0L);
+ }
+
+ inline void CToolBar::Destroy()
+ // Allows CToolBar to be reused after the window is destroyed
+ {
+ CWnd::Destroy();
+ m_StringMap.clear();
+ }
+
+ inline BOOL CToolBar::DisableButton(int idButton) const
+ // Disables the specified button in a toolbar
+ // An example of idButton would be IDM_FILE_OPEN
+ {
+ assert(::IsWindow(m_hWnd));
+ return (BOOL)SendMessage(TB_ENABLEBUTTON, (WPARAM)idButton, (LPARAM) MAKELONG(FALSE, 0));
+ }
+
+ inline BOOL CToolBar::EnableButton(int idButton) const
+ // Enables the specified button in a toolbar
+ {
+ assert(::IsWindow(m_hWnd));
+ return (BOOL)SendMessage(TB_ENABLEBUTTON, (WPARAM)idButton, (LPARAM) MAKELONG(TRUE,0 ));
+ }
+
+ inline BOOL CToolBar::GetButton(int iButton, LPTBBUTTON lpButton) const
+ // Recieves the TBBUTTON structure information from the specified button
+ {
+ assert(::IsWindow(m_hWnd));
+ return (BOOL)SendMessage(TB_GETBUTTON, (LPARAM)iButton, (WPARAM)lpButton);
+ }
+
+ inline int CToolBar::GetButtonCount() const
+ // Retrieves a count of the buttons currently in the toolbar
+ {
+ assert(::IsWindow(m_hWnd));
+ return (int)SendMessage(TB_BUTTONCOUNT, 0L, 0L);
+ }
+
+ inline DWORD CToolBar::GetButtonSize() const
+ // Retrieves the current width and height of toolbar buttons, in pixels.
+ // Returns a DWORD value that contains the width and height values in the low word and high word, respectively.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (DWORD)SendMessage(TB_GETBUTTONSIZE, 0L, 0L);
+ }
+
+ inline UINT CToolBar::GetButtonState(int idButton) const
+ // Get the state of an individual button
+ // TBSTATE_CHECKED The button has the TBSTYLE_CHECK style and is being clicked.
+ // TBSTATE_ELLIPSES The button's text is cut off and an ellipsis is displayed.
+ // TBSTATE_ENABLED The button accepts user input. A button that doesn't have this state is grayed.
+ // TBSTATE_HIDDEN The button is not visible and cannot receive user input.
+ // TBSTATE_INDETERMINATE The button is grayed.
+ // TBSTATE_MARKED The button is marked. The interpretation of a marked item is dependent upon the application.
+ // TBSTATE_PRESSED The button is being clicked.
+ // TBSTATE_WRAP The button is followed by a line break.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (UINT)SendMessage(TB_GETSTATE, (WPARAM) idButton, 0L);
+ }
+
+ inline BYTE CToolBar::GetButtonStyle(int idButton) const
+ // Get the the style of the toolbar control. The following button styles are supported:
+ // TBSTYLE_BUTTON Standard pushbutton (default)
+ // TBSTYLE_SEP Separator
+ // TBSTYLE_CHECK Auto check-box button
+ // TBSTYLE_GROUP Marks the start of a group of buttons
+ // TBSTYLE_CHECKGROUP Marks the start of a group of check-box buttons
+ // TBSTYLE_DROPDOWN Creates a drop-down list button
+ // TBSTYLE_AUTOSIZE The button's width will be calculated based on the text of the button, not on the size of the image
+ // TBSTYLE_NOPREFIX The button text will not have an accelerator prefix associated with it
+ {
+ assert(::IsWindow(m_hWnd));
+
+ int iIndex = CommandToIndex(idButton);
+ TBBUTTON tbb = {0};
+ SendMessage(TB_GETBUTTON, iIndex, (LPARAM) &tbb);
+
+ return tbb.fsStyle;
+ }
+
+ inline CString CToolBar::GetButtonText(int idButton) const
+ // Retrieves the display text of a button on a toolbar.
+ {
+ assert(::IsWindow(m_hWnd));
+
+ int Length = (int)SendMessage(TB_GETBUTTONTEXT, idButton, 0);
+ CString str;
+ LPTSTR szStr = str.GetBuffer(Length +1);
+ SendMessage(TB_GETBUTTONTEXT, (LPARAM)idButton, (WPARAM)szStr);
+ str.ReleaseBuffer();
+ return str;
+ }
+
+ inline int CToolBar::GetCommandID(int iIndex) const
+ // Retrieves information about the specified button in a toolbar
+ {
+ assert(::IsWindow(m_hWnd));
+ TBBUTTON tbb = {0};
+ SendMessage(TB_GETBUTTON, iIndex, (WPARAM) &tbb);
+
+ // returns zero if failed
+ return tbb.idCommand;
+ }
+
+ inline HIMAGELIST CToolBar::GetDisabledImageList() const
+ // Retrieves the image list that a toolbar control uses to display inactive buttons.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (HIMAGELIST)SendMessage(TB_GETDISABLEDIMAGELIST, 0L, 0L);
+ }
+
+ inline HIMAGELIST CToolBar::GetHotImageList() const
+ // Retrieves the image list that a toolbar control uses to display hot buttons.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (HIMAGELIST)SendMessage(TB_GETHOTIMAGELIST, 0L, 0L);
+ }
+
+ inline int CToolBar::GetHotItem() const
+ // Retrieves the index of the hot item in a toolbar, or -1 if no hot item is set.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (int)SendMessage(TB_GETHOTITEM, 0L, 0L);
+ }
+
+ inline HIMAGELIST CToolBar::GetImageList() const
+ // Retrieves the image list that a toolbar control uses to display buttons in their default state.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (HIMAGELIST)SendMessage(TB_GETIMAGELIST, 0L, 0L);
+ }
+
+ inline CRect CToolBar::GetItemRect(int iIndex) const
+ // Retrieves the bounding rectangle of a button in a toolbar
+ {
+ assert(::IsWindow(m_hWnd));
+ CRect rc;
+ int iCount = (int)SendMessage(TB_BUTTONCOUNT, 0L, 0L);
+
+ if (iCount >= iIndex)
+ SendMessage(TB_GETITEMRECT, (WPARAM)iIndex, (LPARAM)&rc);
+
+ return rc;
+ }
+
+ inline CSize CToolBar::GetMaxSize() const
+ // Retrieves the total size of all of the visible buttons and separators in the toolbar
+ {
+ assert(::IsWindow(m_hWnd));
+ CSize sz;
+ SendMessage(TB_GETMAXSIZE, 0L, (LPARAM)&sz);
+
+ // This fixes a Windows bug calculating the size when TBSTYLE_DROPDOWN is used.
+ int xMaxSize = 0;
+ for (int i= 0 ; i < GetButtonCount(); ++i)
+ {
+ xMaxSize += GetItemRect(i).Width();
+ }
+
+ sz.cx = xMaxSize;
+ return sz;
+ }
+
+ inline DWORD CToolBar::GetPadding() const
+ // Returns a DWORD value that contains the horizontal padding in the low word and the vertical padding in the high word, in pixels.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (DWORD)SendMessage(TB_GETPADDING, 0L, 0L);
+ }
+
+ inline CRect CToolBar::GetRect(int idButton) const
+ // Retrieves the bounding rectangle for a specified toolbar button.
+ {
+ assert(::IsWindow(m_hWnd));
+ CRect rc;
+ SendMessage(TB_GETRECT, (WPARAM)idButton, (LPARAM)&rc);
+ return rc;
+ }
+
+ inline int CToolBar::GetRows() const
+ // Retrieves the number of rows of buttons in a toolbar with the TBSTYLE_WRAPABLE style.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (int)SendMessage(TB_GETROWS, 0L, 0L);
+ }
+
+ inline int CToolBar::GetTextRows() const
+ // Retrieves the maximum number of text rows that can be displayed on a toolbar button.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (int)SendMessage(TB_GETTEXTROWS, 0L, 0L);
+ }
+
+ inline HWND CToolBar::GetToolTips() const
+ // Retrieves the handle to the ToolTip control, if any, associated with the toolbar.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (HWND)SendMessage(TB_GETTOOLTIPS, 0L, 0L);
+ }
+
+ inline BOOL CToolBar::HasText() const
+ {
+ assert(::IsWindow(m_hWnd));
+ BOOL bReturn = FALSE;
+
+ for (int i = 0 ; i < GetButtonCount(); ++i)
+ {
+ if (SendMessage(TB_GETBUTTONTEXT, GetCommandID(i), 0L) != -1)
+ bReturn = TRUE;
+ }
+
+ // return TRUE if any button has text
+ return bReturn;
+ }
+
+ inline BOOL CToolBar::HideButton(int idButton, BOOL fShow) const
+ //Hides or shows the specified button in a toolbar.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (BOOL)SendMessage(TB_HIDEBUTTON, (WPARAM)idButton, (LPARAM)MAKELONG (fShow, 0));
+ }
+
+ inline int CToolBar::HitTest() const
+ // Determines where a point lies in a toolbar control.
+
+ // We do our own hit test since TB_HITTEST is a bit buggy,
+ // and also doesn't work at all on earliest versions of Win95
+ {
+ assert(::IsWindow(m_hWnd));
+ CPoint pt = GetCursorPos();
+ ScreenToClient(pt);
+
+ int nButtons = (int)SendMessage(TB_BUTTONCOUNT, 0L, 0L);
+ int iButton = -1;
+
+ for (int i = 0 ; i < nButtons; ++i)
+ {
+ CRect rc = GetItemRect(i);
+ if (rc.PtInRect(pt))
+ iButton = i;
+ }
+
+ return iButton;
+ }
+
+ inline BOOL CToolBar::Indeterminate(int idButton, BOOL fIndeterminate) const
+ //Hides or shows the specified button in a toolbar.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (BOOL)SendMessage(TB_INDETERMINATE, (WPARAM)idButton, (LPARAM)MAKELONG (fIndeterminate, 0));
+ }
+
+ inline BOOL CToolBar::InsertButton(int iButton, LPTBBUTTON lpButton) const
+ // Inserts a button in a toolbar.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (BOOL)SendMessage(TB_INSERTBUTTON, (WPARAM)iButton, (LPARAM)lpButton);
+ }
+
+ inline BOOL CToolBar::IsButtonHidden(int idButton) const
+ // Determines whether the specified button in a toolbar is hidden.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (BOOL)SendMessage(TB_ISBUTTONHIDDEN, (WPARAM)idButton, 0L);
+ }
+
+ inline BOOL CToolBar::IsButtonHighlighted(int idButton) const
+ // Checks the highlight state of a toolbar button.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (BOOL)SendMessage(TB_ISBUTTONHIGHLIGHTED, (WPARAM)idButton, 0L);
+ }
+
+ inline BOOL CToolBar::IsButtonIndeterminate(int idButton) const
+ // Determines whether the specified button in a toolbar is indeterminate.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (BOOL)SendMessage(TB_ISBUTTONINDETERMINATE, (WPARAM)idButton, 0L);
+ }
+
+ inline BOOL CToolBar::IsButtonPressed(int idButton) const
+ // Determines whether the specified button in a toolbar is pressed.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (BOOL)SendMessage(TB_ISBUTTONPRESSED, (WPARAM)idButton, 0L);
+ }
+
+ inline int CToolBar::MapAccelerator(TCHAR chAccel) const
+ // Determines whether the specified button in a toolbar is pressed.
+ {
+ assert(::IsWindow(m_hWnd));
+ int uButtonID;
+ int idButton;
+ if (SendMessage(TB_MAPACCELERATOR, (WPARAM)chAccel, (LPARAM)&uButtonID))
+ idButton = uButtonID;
+ else
+ idButton = -1;
+
+ return idButton;
+ }
+
+ inline BOOL CToolBar::MarkButton(int idButton) const
+ // Sets the highlight state of a given button in a toolbar control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (BOOL)SendMessage(TB_MARKBUTTON, (WPARAM)idButton, 0L);
+ }
+
+ inline BOOL CToolBar::MoveButton(UINT uOldPos, UINT uNewPos) const
+ // Moves a button from one index to another.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (BOOL)SendMessage(TB_MOVEBUTTON, (WPARAM)uOldPos, (LPARAM)uNewPos);
+ }
+
+
+ inline void CToolBar::OnCreate()
+ {
+ // We must send this message before sending the TB_ADDBITMAP or TB_ADDBUTTONS message
+ SendMessage(TB_BUTTONSTRUCTSIZE, (WPARAM)sizeof(TBBUTTON), 0L);
+
+ // allows buttons to have a separate dropdown arrow
+ // Note: TBN_DROPDOWN notification is sent by a toolbar control when the user clicks a dropdown button
+ SendMessage(TB_SETEXTENDEDSTYLE, 0L, TBSTYLE_EX_DRAWDDARROWS);
+
+ // Turn of Double click processing (i.e. treat a double click as two single clicks)
+ DWORD dwStyle = (DWORD)GetClassLongPtr(GCL_STYLE);
+ dwStyle &= ~CS_DBLCLKS;
+ SetClassLongPtr(GCL_STYLE, dwStyle);
+
+ // Add extra styles for toolbars inside a rebar
+ if (lstrcmp(GetParent()->GetClassName(), _T("ReBarWindow32")) == 0)
+ {
+ DWORD style = (DWORD)GetWindowLongPtr(GWL_STYLE);
+ style |= CCS_NODIVIDER | CCS_NORESIZE;
+ SetWindowLongPtr(GWL_STYLE, style);
+ }
+
+ SetButtons(m_vToolBarData);
+
+ // Set rows of text to zero
+ SendMessage(TB_SETMAXTEXTROWS, 0L, 0L);
+ }
+
+ inline LRESULT CToolBar::OnCustomDraw(NMHDR* pNMHDR)
+ // With CustomDraw we manually control the drawing of each toolbar button
+ {
+ LPNMTBCUSTOMDRAW lpNMCustomDraw = (LPNMTBCUSTOMDRAW)pNMHDR;
+
+ switch (lpNMCustomDraw->nmcd.dwDrawStage)
+ {
+ // Begin paint cycle
+ case CDDS_PREPAINT:
+ // Send NM_CUSTOMDRAW item draw, and post-paint notification messages.
+ return CDRF_NOTIFYITEMDRAW | CDRF_NOTIFYPOSTPAINT ;
+
+ // An item is about to be drawn
+ case CDDS_ITEMPREPAINT:
+ {
+ CDC* pDrawDC = FromHandle(lpNMCustomDraw->nmcd.hdc);
+ CRect rcRect = lpNMCustomDraw->nmcd.rc;
+ int nState = lpNMCustomDraw->nmcd.uItemState;
+ DWORD dwItem = (DWORD)lpNMCustomDraw->nmcd.dwItemSpec;
+ DWORD dwTBStyle = (DWORD)SendMessage(TB_GETSTYLE, 0L, 0L);
+ int nStyle = GetButtonStyle(dwItem);
+
+ int nButton = (int)SendMessage(TB_COMMANDTOINDEX, (WPARAM) dwItem, 0L);
+ TBBUTTON tbb = {0};
+ SendMessage(TB_GETBUTTON, nButton, (LPARAM)&tbb);
+ int iImage = (int)tbb.dwData;
+
+ // Calculate text size
+ std::vector<TCHAR> vText(MAX_MENU_STRING, _T('\0'));
+ TCHAR* pszText = &vText[0];
+ CSize TextSize;
+ if (HasText()) // Does any button have text?
+ {
+ pDrawDC->SelectObject(GetFont());
+ if (SendMessage(TB_GETBUTTONTEXT, dwItem, (LPARAM)pszText)> 0)
+ {
+ TextSize = pDrawDC->GetTextExtentPoint32(pszText, lstrlen(pszText));
+ }
+ }
+
+ // Draw outline rectangle
+ if (nState & (CDIS_HOT | CDIS_SELECTED | CDIS_CHECKED))
+ {
+ pDrawDC->CreatePen(PS_SOLID, 1, m_Theme.clrOutline);
+ pDrawDC->MoveTo(rcRect.left, rcRect.top);
+ pDrawDC->LineTo(rcRect.left, rcRect.bottom-1);
+ pDrawDC->LineTo(rcRect.right-1, rcRect.bottom-1);
+ pDrawDC->LineTo(rcRect.right-1, rcRect.top);
+ pDrawDC->LineTo(rcRect.left, rcRect.top);
+ }
+
+ // Draw filled gradient background
+ rcRect.InflateRect(-1, -1);
+ if ((nState & (CDIS_SELECTED|CDIS_CHECKED)) || (GetButtonState(dwItem) & TBSTATE_PRESSED))
+ {
+ pDrawDC->GradientFill(m_Theme.clrPressed1, m_Theme.clrPressed2, rcRect, FALSE);
+ }
+ else if (nState & CDIS_HOT)
+ {
+ pDrawDC->GradientFill(m_Theme.clrHot1, m_Theme.clrHot2, rcRect, FALSE);
+ }
+
+ // Get the appropriate image list depending on the button state
+ HIMAGELIST himlToolBar;
+ if (nState & CDIS_DISABLED)
+ {
+ himlToolBar = (HIMAGELIST)SendMessage(TB_GETDISABLEDIMAGELIST, 0L, 0L);
+ }
+ else if (nState & (CDIS_HOT | CDIS_SELECTED | CDIS_CHECKED))
+ {
+ himlToolBar = (HIMAGELIST)SendMessage(TB_GETHOTIMAGELIST, 0L, 0L);
+ if (0 == himlToolBar)
+ himlToolBar = (HIMAGELIST)SendMessage(TB_GETIMAGELIST, 0L, 0L);
+ }
+ else
+ {
+ himlToolBar = (HIMAGELIST)SendMessage(TB_GETIMAGELIST, 0L, 0L);
+ }
+
+ BOOL IsWin95 = (1400 == (GetWinVersion()) || (2400 == GetWinVersion()));
+
+ // Calculate image position
+ int cxImage = 0;
+ int cyImage = 0;
+ ImageList_GetIconSize(himlToolBar, &cxImage, &cyImage);
+
+ int yImage = (rcRect.bottom - rcRect.top - cyImage - TextSize.cy +2)/2;
+ int xImage = (rcRect.right + rcRect.left - cxImage)/2 + ((nState & (CDIS_SELECTED|CDIS_CHECKED))? 1:0);
+ if (dwTBStyle & TBSTYLE_LIST)
+ {
+ xImage = rcRect.left + (IsXPThemed()?2:4) + ((nState & CDIS_SELECTED)? 1:0);
+ yImage = (rcRect.bottom -rcRect.top - cyImage +2)/2 + ((nState & (CDIS_SELECTED|CDIS_CHECKED))? 1:0);
+ }
+
+ // Handle the TBSTYLE_DROPDOWN and BTNS_WHOLEDROPDOWN styles
+ if ((nStyle & TBSTYLE_DROPDOWN) || ((nStyle & 0x0080) && (!IsWin95)))
+ {
+ // Calculate the dropdown arrow position
+ int xAPos = (nStyle & TBSTYLE_DROPDOWN)? rcRect.right -6 : (rcRect.right + rcRect.left + cxImage + 4)/2;
+ int yAPos = (nStyle & TBSTYLE_DROPDOWN)? (rcRect.bottom - rcRect.top +1)/2 : (cyImage)/2;
+ if (dwTBStyle & TBSTYLE_LIST)
+ {
+ xAPos = (nStyle & TBSTYLE_DROPDOWN)?rcRect.right -6:rcRect.right -5;
+ yAPos = (rcRect.bottom - rcRect.top +1)/2 + ((nStyle & TBSTYLE_DROPDOWN)?0:1);
+ }
+
+ xImage -= (nStyle & TBSTYLE_DROPDOWN)?((dwTBStyle & TBSTYLE_LIST)? (IsXPThemed()?-4:0):6):((dwTBStyle & TBSTYLE_LIST)? 0:4);
+
+ // Draw separate background for dropdown arrow
+ if ((m_bDrawArrowBkgrnd) && (nState & CDIS_HOT))
+ {
+ CRect rcArrowBkgnd = rcRect;
+ rcArrowBkgnd.left = rcArrowBkgnd.right - 13;
+ pDrawDC->GradientFill(m_Theme.clrPressed1, m_Theme.clrPressed2, rcArrowBkgnd, FALSE);
+ }
+
+ m_bDrawArrowBkgrnd = FALSE;
+
+ // Manually draw the dropdown arrow
+ pDrawDC->CreatePen(PS_SOLID, 1, RGB(0,0,0));
+ for (int i = 2; i >= 0; --i)
+ {
+ pDrawDC->MoveTo(xAPos -i-1, yAPos - i+1);
+ pDrawDC->LineTo(xAPos +i, yAPos - i+1);
+ }
+
+ // Draw line between icon and dropdown arrow
+ if ((nStyle & TBSTYLE_DROPDOWN) && ((nState & CDIS_SELECTED) || nState & CDIS_HOT))
+ {
+ pDrawDC->CreatePen(PS_SOLID, 1, m_Theme.clrOutline);
+ pDrawDC->MoveTo(rcRect.right - 13, rcRect.top);
+ pDrawDC->LineTo(rcRect.right - 13, rcRect.bottom);
+ }
+ }
+
+ // Draw the button image
+ if (xImage > 0)
+ {
+ ImageList_Draw(himlToolBar, iImage, *pDrawDC, xImage, yImage, ILD_TRANSPARENT);
+ }
+
+ //Draw Text
+ if (lstrlen(pszText) > 0)
+ {
+ int iWidth = rcRect.right - rcRect.left - ((nStyle & TBSTYLE_DROPDOWN)?13:0);
+ CRect rcText(0, 0, MIN(TextSize.cx, iWidth), TextSize.cy);
+
+ int xOffset = (rcRect.right + rcRect.left - rcText.right + rcText.left - ((nStyle & TBSTYLE_DROPDOWN)? 11 : 1))/2;
+ int yOffset = yImage + cyImage +1;
+
+ if (dwTBStyle & TBSTYLE_LIST)
+ {
+ xOffset = rcRect.left + cxImage + ((nStyle & TBSTYLE_DROPDOWN)?(IsXPThemed()?10:6): 6) + ((nState & CDIS_SELECTED)? 1:0);
+ yOffset = (2+rcRect.bottom - rcRect.top - rcText.bottom + rcText.top)/2 + ((nState & CDIS_SELECTED)? 1:0);
+ rcText.right = MIN(rcText.right, rcRect.right - xOffset);
+ }
+
+ OffsetRect(&rcText, xOffset, yOffset);
+
+ int iMode = pDrawDC->SetBkMode(TRANSPARENT);
+ pDrawDC->SelectObject(GetFont());
+
+ if (nState & (CDIS_DISABLED))
+ {
+ // Draw text twice for embossed look
+ rcText.OffsetRect(1, 1);
+ pDrawDC->SetTextColor(RGB(255,255,255));
+ pDrawDC->DrawText(pszText, lstrlen(pszText), rcText, DT_LEFT);
+ rcText.OffsetRect(-1, -1);
+ pDrawDC->SetTextColor(GetSysColor(COLOR_GRAYTEXT));
+ pDrawDC->DrawText(pszText, lstrlen(pszText), rcText, DT_LEFT);
+ }
+ else
+ {
+ pDrawDC->SetTextColor(GetSysColor(COLOR_BTNTEXT));
+ pDrawDC->DrawText(pszText, lstrlen(pszText), rcText, DT_LEFT | DT_END_ELLIPSIS);
+ }
+ pDrawDC->SetBkMode(iMode);
+ }
+ }
+ return CDRF_SKIPDEFAULT; // No further drawing
+ }
+ return 0L;
+ }
+
+ inline void CToolBar::OnDestroy()
+ {
+ HIMAGELIST himlToolBar = (HIMAGELIST)SendMessage(TB_GETIMAGELIST, 0L, 0L);
+ HIMAGELIST himlToolBarHot = (HIMAGELIST)SendMessage(TB_GETHOTIMAGELIST, 0L, 0L);
+ HIMAGELIST himlToolBarDis = (HIMAGELIST)SendMessage(TB_GETDISABLEDIMAGELIST, 0L, 0L);
+ ImageList_Destroy(himlToolBar);
+ ImageList_Destroy(himlToolBarHot);
+ ImageList_Destroy(himlToolBarDis);
+ }
+
+ inline LRESULT CToolBar::OnNotifyReflect(WPARAM wParam, LPARAM lParam)
+ // Notifications sent to the parent window are reflected back here
+ {
+ UNREFERENCED_PARAMETER(wParam);
+
+ switch (((LPNMHDR)lParam)->code)
+ {
+ case NM_CUSTOMDRAW:
+ {
+ if (m_Theme.UseThemes)
+ return OnCustomDraw((LPNMHDR) lParam);
+ }
+ break;
+
+ case TBN_DROPDOWN:
+ {
+ int iItem = ((LPNMTOOLBAR) lParam)->iItem;
+
+ // a boolean expression
+ m_bDrawArrowBkgrnd = (GetButtonStyle(iItem) & TBSTYLE_DROPDOWN);
+ }
+ break;
+ }
+ return 0L;
+ }
+
+ inline void CToolBar::OnWindowPosChanging(WPARAM wParam, LPARAM lParam)
+ {
+ UNREFERENCED_PARAMETER(wParam);
+
+ // Adjust size for toolbars inside a rebar
+ CWnd* pParent = GetParent();
+ if (lstrcmp(pParent->GetClassName(), _T("ReBarWindow32")) == 0)
+ {
+ ReBarTheme* pTheme = (ReBarTheme*)pParent->SendMessage(UWM_GETREBARTHEME, 0, 0);
+
+ if (pTheme && pTheme->UseThemes && pTheme->ShortBands)
+ {
+ LPWINDOWPOS pWinPos = (LPWINDOWPOS)lParam;
+ pWinPos->cx = GetMaxSize().cx+2;
+ }
+ }
+ }
+
+ inline void CToolBar::PreCreate(CREATESTRUCT &cs)
+ {
+ // Sets the CREATESTRUCT parameters prior to window creation
+ cs.style = WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | TBSTYLE_TOOLTIPS | TBSTYLE_FLAT;
+ }
+
+ inline void CToolBar::PreRegisterClass(WNDCLASS &wc)
+ {
+ // Set the Window Class
+ wc.lpszClassName = TOOLBARCLASSNAME;
+ }
+
+ inline BOOL CToolBar::PressButton(int idButton, BOOL fPress) const
+ // Presses or releases the specified button in a toolbar.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (BOOL)SendMessage(TB_PRESSBUTTON, (WPARAM)idButton, (LPARAM)MAKELONG(fPress, 0));
+ }
+
+ inline BOOL CToolBar::ReplaceBitmap(UINT NewToolBarID)
+ // Replaces an existing bitmap with a new bitmap.
+
+ // Note: ReplaceBitmap supports a maximum colour depth of 8 bits (256 colours)
+ // For more colours, use an ImageList instead
+ {
+ assert(::IsWindow(m_hWnd));
+
+ int iNumButtons = 0;
+ std::vector<UINT>::iterator iter;
+ for (iter = GetToolBarData().begin(); iter < GetToolBarData().end(); ++iter)
+ if ((*iter) != 0) ++iNumButtons;
+
+ TBREPLACEBITMAP tbrb = {0};
+ tbrb.hInstNew = GetApp()->GetResourceHandle();
+ tbrb.hInstOld = GetApp()->GetResourceHandle();
+ tbrb.nIDNew = NewToolBarID;
+ tbrb.nIDOld = m_OldToolBarID;
+ tbrb.nButtons = iNumButtons;
+
+ BOOL bResult = (BOOL)SendMessage(TB_REPLACEBITMAP, iNumButtons, (LPARAM)&tbrb);
+ if (bResult)
+ m_OldToolBarID = NewToolBarID;
+
+ return bResult;
+ }
+
+ inline void CToolBar::SaveRestore(BOOL fSave, TBSAVEPARAMS* ptbsp) const
+ // Presses or releases the specified button in a toolbar.
+ {
+ assert(::IsWindow(m_hWnd));
+ SendMessage(TB_PRESSBUTTON, (WPARAM)fSave, (LPARAM)ptbsp);
+ }
+
+ inline BOOL CToolBar::SetBitmap(UINT nID)
+ // Set the button images
+ {
+ assert(::IsWindow(m_hWnd));
+
+ CBitmap Bitmap(nID);
+ assert (Bitmap.GetHandle());
+ BITMAP bm = Bitmap.GetBitmapData();
+
+ int iNumButtons = 0;
+ std::vector<UINT>::iterator iter;
+ for (iter = GetToolBarData().begin(); iter < GetToolBarData().end(); ++iter)
+ if ((*iter) != 0) ++iNumButtons;
+
+ int iImageWidth = bm.bmWidth / iNumButtons;
+ int iImageHeight = bm.bmHeight;
+
+ // Set the bitmap size first
+ SetBitmapSize(iImageWidth, iImageHeight);
+
+ BOOL bResult = FALSE;
+ if (m_OldToolBarID)
+ bResult = ReplaceBitmap(nID);
+ else
+ bResult = (BOOL)AddBitmap(nID);
+
+ return bResult;
+ }
+
+ inline BOOL CToolBar::SetBitmapSize(int cx, int cy) const
+ // Sets the size of the bitmapped images to be added to a toolbar.
+
+ // Needs to be used when the image size is not the default 16 x 15
+ // Call this function before using AddBitmap or ReplaceBitmap
+ {
+ assert(::IsWindow(m_hWnd));
+ return (BOOL)SendMessage(TB_SETBITMAPSIZE, 0L, MAKELONG(cx, cy));
+ }
+
+ inline int CToolBar::SetButtons(const std::vector<UINT>& vToolBarData) const
+ // Assigns a resource ID to each toolbar button
+ {
+ assert(::IsWindow(m_hWnd));
+
+ int iImages = 0;
+ UINT iNumButtons = (UINT)vToolBarData.size();
+
+ // Remove any existing buttons
+ while (SendMessage(TB_BUTTONCOUNT, 0L, 0L) > 0)
+ {
+ if(!SendMessage(TB_DELETEBUTTON, 0L, 0L))
+ break;
+ }
+
+ if (iNumButtons > 0)
+ {
+ // TBBUTTON structure for each button in the toolbar
+ TBBUTTON tbb = {0};
+
+ for (UINT j = 0 ; j < iNumButtons; ++j)
+ {
+ ZeroMemory(&tbb, sizeof(TBBUTTON));
+
+ if (0 == vToolBarData[j])
+ {
+ tbb.fsStyle = TBSTYLE_SEP;
+ }
+ else
+ {
+ tbb.dwData = iImages;
+ tbb.iBitmap = iImages;
+ tbb.idCommand = vToolBarData[j];
+ tbb.fsState = TBSTATE_ENABLED;
+ tbb.fsStyle = TBSTYLE_BUTTON;
+ }
+
+ // Add the button to the toolbar
+ if (SendMessage(TB_ADDBUTTONS, 1L, (LPARAM)&tbb))
+ iImages++;
+ else
+ break;
+ }
+ }
+
+ return iImages;
+ }
+
+ inline BOOL CToolBar::SetButtonSize(int cx, int cy) const
+ // Sets the size of the buttons to be added to a toolbar
+ // The size can be set only before adding any buttons to the toolbar
+ {
+ assert(::IsWindow(m_hWnd));
+ return (BOOL)SendMessage(TB_SETBUTTONSIZE, 0L, MAKELONG(cx, cy));
+ }
+
+ inline BOOL CToolBar::SetButtonState(int idButton, UINT State) const
+ {
+ // Set the state of an individual button
+ // TBSTATE_CHECKED The button has the TBSTYLE_CHECK style and is being clicked.
+ // TBSTATE_ELLIPSES The button's text is cut off and an ellipsis is displayed.
+ // TBSTATE_ENABLED The button accepts user input. A button that doesn't have this state is grayed.
+ // TBSTATE_HIDDEN The button is not visible and cannot receive user input.
+ // TBSTATE_INDETERMINATE The button is grayed.
+ // TBSTATE_MARKED The button is marked. The interpretation of a marked item is dependent upon the application.
+ // TBSTATE_PRESSED The button is being clicked.
+ // TBSTATE_WRAP The button is followed by a line break.
+
+ assert(::IsWindow(m_hWnd));
+ return (BOOL)SendMessage(TB_SETSTATE, (WPARAM) idButton, (LPARAM)MAKELONG (State, 0));
+ }
+
+ inline BOOL CToolBar::SetButtonStyle(int idButton, BYTE Style) const
+ // The the style of the toolbar control. The following button styles are supported:
+ // TBSTYLE_BUTTON Standard pushbutton (default)
+ // TBSTYLE_SEP Separator
+ // TBSTYLE_CHECK Auto check-box button
+ // TBSTYLE_GROUP Marks the start of a group of buttons
+ // TBSTYLE_CHECKGROUP Marks the start of a group of check-box buttons
+ // TBSTYLE_DROPDOWN Creates a drop-down list button
+ // TBSTYLE_AUTOSIZE The button's width will be calculated based on the text of the button, not on the size of the image
+ // TBSTYLE_NOPREFIX The button text will not have an accelerator prefix associated with it
+ {
+ assert(::IsWindow(m_hWnd));
+
+ TBBUTTONINFO tbbi = {0};
+ tbbi.cbSize = sizeof(TBBUTTONINFO);
+ tbbi.dwMask = TBIF_STYLE;
+ tbbi.fsStyle = Style;
+
+ // Note: TB_SETBUTTONINFO requires comctl32.dll version 4.71 or later
+ // i.e. Win95 with IE4 / NT with IE4 or later
+ return (BOOL)SendMessage(TB_SETBUTTONINFO, idButton, (LPARAM) &tbbi);
+ }
+
+ inline BOOL CToolBar::SetButtonText(int idButton, LPCTSTR szText)
+ // This rather convoluted approach to setting toolbar button text supports
+ // all versions of Windows, including Win95 with COMCTL32.DLL version 4.0
+ {
+ assert(::IsWindow(m_hWnd));
+ int iIndex = CommandToIndex(idButton);
+ assert(-1 != iIndex);
+
+ BOOL Succeeded = TRUE;
+ tString sString = szText;
+ std::map<tString, int>::iterator m;
+ int iString;
+
+ // Check to see if the string is already added
+ m = m_StringMap.find(sString);
+ if (m_StringMap.end() == m)
+ {
+ if (0 == m_StringMap.size())
+ {
+ // Place a blank string first in the string table, in case some
+ // buttons don't have text
+ TCHAR szString[3] = _T(" ");
+ szString[2] = _T('\0'); // Double-null terminate
+ SendMessage(TB_ADDSTRING, 0L, (LPARAM)szString);
+ }
+
+ // No index for this string exists, so create it now
+ TCHAR szBuf[80] = _T("");
+ lstrcpyn(szBuf, szText, 79);
+ szBuf[lstrlen(szBuf)+1] = _T('\0'); // Double-null terminate
+
+ iString = (int)SendMessage(TB_ADDSTRING, 0L, (LPARAM)szBuf);
+ if (-1 == iString )
+ Succeeded = FALSE;
+
+ // Save the string its index in our map
+ m_StringMap.insert(std::make_pair(sString, iString));
+ }
+ else
+ {
+ // String found, use the index from our map
+ iString = m->second;
+ }
+
+ if (Succeeded)
+ {
+ TBBUTTON tbb = {0};
+ Succeeded = (BOOL)SendMessage(TB_GETBUTTON, iIndex, (LPARAM)&tbb);
+
+ tbb.iString = iString;
+
+ // Turn off ToolBar drawing
+ SendMessage(WM_SETREDRAW, FALSE, 0L);
+
+ if (Succeeded)
+ Succeeded = (BOOL)SendMessage(TB_DELETEBUTTON, iIndex, 0L);
+
+ if (Succeeded)
+ Succeeded = (BOOL)SendMessage(TB_INSERTBUTTON, iIndex, (LPARAM)&tbb);
+
+ // Ensure the button now includes some text rows
+ if (0 == SendMessage(TB_GETTEXTROWS, 0L, 0L))
+ SendMessage(TB_SETMAXTEXTROWS, 1L, 0L);
+
+ // Turn on ToolBar drawing
+ SendMessage(WM_SETREDRAW, TRUE, 0L);
+ }
+ // Redraw button
+ CRect r = GetItemRect(iIndex);
+ InvalidateRect(&r, TRUE);
+
+ return Succeeded;
+ }
+
+ inline BOOL CToolBar::SetButtonWidth(int idButton, int nWidth) const
+ // The set button width can adjust the width of the button after it is created.
+ // This is useful when replacing a button with a ComboBox or other control.
+ // Note: TB_SETBUTTONINFO requires comctl32.dll version 4.71 or later
+ // i.e. Win95 with IE4 / NT with IE4 or later
+ {
+ assert(::IsWindow(m_hWnd));
+
+ TBBUTTONINFO tbbi = {0};
+ tbbi.cbSize = sizeof(TBBUTTONINFO);
+ tbbi.dwMask = TBIF_SIZE;
+ tbbi.cx = (WORD)nWidth;
+ BOOL bResult = (BOOL)SendMessage(TB_SETBUTTONINFO, (WPARAM)idButton, (LPARAM)&tbbi);
+
+ // Send a changed message to the parent (used by the rebar)
+ SIZE MaxSize = GetMaxSize();
+ GetParent()->SendMessage(UWM_TOOLBAR_RESIZE, (WPARAM)m_hWnd, (LPARAM)&MaxSize);
+
+ return bResult;
+ }
+
+ inline BOOL CToolBar::SetCommandID(int iIndex, int idButton) const
+ // Sets the command identifier of a toolbar button
+ {
+ assert(::IsWindow(m_hWnd));
+ return (BOOL)SendMessage(TB_SETCMDID, iIndex, idButton);
+ }
+
+ inline HIMAGELIST CToolBar::SetDisableImageList(HIMAGELIST himlNewDisabled) const
+ // Sets the image list that the toolbar control will use to display disabled buttons.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (HIMAGELIST)SendMessage(TB_SETDISABLEDIMAGELIST, 0L, (LPARAM)himlNewDisabled);
+ }
+
+ inline DWORD CToolBar::SetDrawTextFlags(DWORD dwMask, DWORD dwDTFlags) const
+ // Sets the text drawing flags for the toolbar.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (DWORD)SendMessage(TB_SETDRAWTEXTFLAGS, (WPARAM)dwMask, (LPARAM)dwDTFlags);
+ }
+
+ inline DWORD CToolBar::SetExtendedStyle(DWORD dwExStyle) const
+ // Sets the text drawing flags for the toolbar.
+ // Extended styles include: TBSTYLE_EX_DRAWDDARROWS, TBSTYLE_EX_HIDECLIPPEDBUTTONS, TBSTYLE_EX_DOUBLEBUFFER and TBSTYLE_EX_MIXEDBUTTONS
+ {
+ assert(::IsWindow(m_hWnd));
+ return (DWORD)SendMessage(TB_SETEXTENDEDSTYLE, 0L, (LPARAM)dwExStyle);
+ }
+
+ inline HIMAGELIST CToolBar::SetHotImageList(HIMAGELIST himlNewHot) const
+ // Sets the image list that the toolbar control will use to display hot buttons.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (HIMAGELIST)SendMessage(TB_SETHOTIMAGELIST, 0L, (LPARAM)himlNewHot);
+ }
+
+ inline int CToolBar::SetHotItem(int iHot) const
+ // Sets the hot item in a toolbar.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (int)SendMessage(TB_SETHOTITEM, (WPARAM)iHot, 0L);
+ }
+
+ inline HIMAGELIST CToolBar::SetImageList(HIMAGELIST himlNew) const
+ // Sets the image list that the toolbar will use to display buttons that are in their default state.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (HIMAGELIST)SendMessage(TB_SETIMAGELIST, 0L, (LPARAM)himlNew);
+ }
+
+ inline BOOL CToolBar::SetImages(COLORREF crMask, UINT ToolBarID, UINT ToolBarHotID, UINT ToolBarDisabledID)
+ // Either sets the imagelist or adds/replaces bitmap depending on ComCtl32.dll version
+ // Assumes the width of the button image = bitmap_size / buttons
+ // Assumes buttons have been already been added via AdddToolBarButton
+ // The colour mask is often grey RGB(192,192,192) or magenta (255,0,255);
+ // The color mask is ignored for 32bit bitmap resources
+ // The Hot and disiabled bitmap resources can be 0
+ {
+ assert(::IsWindow(m_hWnd));
+
+ // ToolBar ImageLists require Comctl32.dll version 4.7 or later
+ if (400 == GetComCtlVersion())
+ {
+ // We are using COMCTL32.DLL version 4.0, so we can't use an imagelist.
+ // Instead we simply set the bitmap.
+ return SetBitmap(ToolBarID);
+ }
+
+ int iNumButtons = 0;
+ std::vector<UINT>::iterator iter;
+ for (iter = GetToolBarData().begin(); iter < GetToolBarData().end(); ++iter)
+ if ((*iter) != 0) ++iNumButtons;
+
+ if (iNumButtons > 0)
+ {
+ // Set the button images
+ CBitmap Bitmap(ToolBarID);
+ assert(Bitmap.GetHandle());
+
+ BITMAP bm = Bitmap.GetBitmapData();
+ int iImageWidth = bm.bmWidth / iNumButtons;
+ int iImageHeight = bm.bmHeight;
+
+ HIMAGELIST himlToolBar = (HIMAGELIST)SendMessage(TB_GETIMAGELIST, 0L, 0L);
+ HIMAGELIST himlToolBarHot = (HIMAGELIST)SendMessage(TB_GETHOTIMAGELIST, 0L, 0L);
+ HIMAGELIST himlToolBarDis = (HIMAGELIST)SendMessage(TB_GETDISABLEDIMAGELIST, 0L, 0L);
+ ImageList_Destroy(himlToolBar);
+ ImageList_Destroy(himlToolBarHot);
+ ImageList_Destroy(himlToolBarDis);
+
+ himlToolBar = ImageList_Create(iImageWidth, iImageHeight, ILC_COLOR32 | ILC_MASK, iNumButtons, 0);
+ assert(himlToolBar);
+
+ ImageList_AddMasked(himlToolBar, Bitmap, crMask);
+ SendMessage(TB_SETIMAGELIST, 0L, (LPARAM)himlToolBar);
+
+ if (ToolBarHotID)
+ {
+ CBitmap BitmapHot(ToolBarHotID);
+ assert(BitmapHot);
+
+ himlToolBarHot = ImageList_Create(iImageWidth, iImageHeight, ILC_COLOR32 | ILC_MASK, iNumButtons, 0);
+ assert(himlToolBarHot);
+
+ ImageList_AddMasked(himlToolBarHot, BitmapHot, crMask);
+ SendMessage(TB_SETHOTIMAGELIST, 0L, (LPARAM)himlToolBarHot);
+ }
+
+ if (ToolBarDisabledID)
+ {
+ CBitmap BitmapDisabled(ToolBarDisabledID);
+ assert(BitmapDisabled);
+
+ himlToolBarDis = ImageList_Create(iImageWidth, iImageHeight, ILC_COLOR32 | ILC_MASK, iNumButtons, 0);
+ assert(himlToolBarDis);
+
+ ImageList_AddMasked(himlToolBarDis, BitmapDisabled, crMask);
+ SendMessage(TB_SETDISABLEDIMAGELIST, 0L, (LPARAM)himlToolBarDis);
+ }
+ else
+ {
+ himlToolBarDis = CreateDisabledImageList(himlToolBar);
+ SendMessage(TB_SETDISABLEDIMAGELIST, 0L, (LPARAM)himlToolBarDis);
+ }
+
+ // Inform the parent of the change (rebar needs this)
+ SIZE MaxSize = GetMaxSize();
+ GetParent()->SendMessage(UWM_TOOLBAR_RESIZE, (WPARAM)m_hWnd, (LPARAM)&MaxSize);
+ }
+
+ return TRUE;
+ }
+
+ inline BOOL CToolBar::SetIndent(int iIndent) const
+ // Sets the indentation for the first button in a toolbar control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (BOOL)SendMessage(TB_SETINDENT, (WPARAM)iIndent, 0L);
+ }
+
+ inline BOOL CToolBar::SetMaxTextRows(int iMaxRows) const
+ // Sets the maximum number of text rows displayed on a toolbar button.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (BOOL)SendMessage(TB_SETMAXTEXTROWS, (WPARAM)iMaxRows, 0L);
+ }
+
+ inline BOOL CToolBar::SetPadding(int cx, int cy) const
+ // Sets the padding for a toolbar control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (BOOL)SendMessage(TB_SETPADDING, 0L, (WPARAM)MAKELONG(cx, cy));
+ }
+
+ inline void CToolBar::SetToolBarTheme(ToolBarTheme& Theme)
+ {
+ m_Theme.UseThemes = Theme.UseThemes;
+ m_Theme.clrHot1 = Theme.clrHot1;
+ m_Theme.clrHot2 = Theme.clrHot2;
+ m_Theme.clrPressed1 = Theme.clrPressed1;
+ m_Theme.clrPressed2 = Theme.clrPressed2;
+ m_Theme.clrOutline = Theme.clrOutline;
+
+ if (IsWindow())
+ Invalidate();
+ }
+
+ inline void CToolBar::SetToolTips(HWND hwndToolTip) const
+ // Associates a ToolTip control with a toolbar.
+ {
+ assert(::IsWindow(m_hWnd));
+ SendMessage(TB_SETTOOLTIPS, (WPARAM)hwndToolTip, 0L);
+ }
+
+ inline LRESULT CToolBar::WndProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam)
+ {
+ switch (uMsg)
+ {
+ case WM_DESTROY:
+ OnDestroy();
+ break;
+ case UWM_GETTOOLBARTHEME:
+ {
+ ToolBarTheme& tt = GetToolBarTheme();
+ return (LRESULT)&tt;
+ }
+ case WM_WINDOWPOSCHANGING:
+ OnWindowPosChanging(wParam, lParam);
+ break;
+ }
+
+ // pass unhandled messages on for default processing
+ return CWnd::WndProcDefault(uMsg, wParam, lParam);
+ }
+
+} // namespace Win32xx
+
+#endif // #ifndef _WIN32XX_TOOLBAR_H_
diff --git a/mmc_updater/depends/win32cpp/treeview.h b/mmc_updater/depends/win32cpp/treeview.h
new file mode 100644
index 00000000..4186e9ce
--- /dev/null
+++ b/mmc_updater/depends/win32cpp/treeview.h
@@ -0,0 +1,624 @@
+// Win32++ Version 7.2
+// Released: 5th AUgust 2011
+//
+// David Nash
+// email: dnash@bigpond.net.au
+// url: https://sourceforge.net/projects/win32-framework
+//
+//
+// Copyright (c) 2005-2011 David Nash
+//
+// Permission is hereby granted, free of charge, to
+// any person obtaining a copy of this software and
+// associated documentation files (the "Software"),
+// to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify,
+// merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom
+// the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice
+// shall be included in all copies or substantial portions
+// of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
+// OR OTHER DEALINGS IN THE SOFTWARE.
+//
+////////////////////////////////////////////////////////
+
+
+
+
+#ifndef _WIN32XX_TREEVIEW_H_
+#define _WIN32XX_TREEVIEW_H_
+
+#include "wincore.h"
+#include "commctrl.h"
+
+// Disable macros from Windowsx.h
+#undef GetNextSibling
+#undef GetPrevSibling
+
+namespace Win32xx
+{
+
+ class CTreeView : public CWnd
+ {
+ public:
+ CTreeView() {}
+ virtual ~CTreeView() {}
+ virtual void PreRegisterClass(WNDCLASS &wc);
+
+// Attributes
+ COLORREF GetBkColor() const;
+ HTREEITEM GetChild(HTREEITEM hItem) const;
+ UINT GetCount() const;
+ HTREEITEM GetDropHiLightItem() const;
+ HWND GetEditControl() const;
+ HTREEITEM GetFirstVisible() const;
+ HIMAGELIST GetImageList(int iImageType) const;
+ UINT GetIndent() const;
+ COLORREF GetInsertMarkColor() const;
+ BOOL GetItem(TVITEM& Item) const;
+ DWORD_PTR GetItemData(HTREEITEM hItem) const;
+ int GetItemHeight() const;
+ BOOL GetItemImage(HTREEITEM hItem, int& nImage, int& nSelectedImage ) const;
+ BOOL GetItemRect(HTREEITEM hItem, CRect& rc, BOOL bTextOnly) const;
+ tString GetItemText(HTREEITEM hItem, UINT nTextMax /* = 260 */) const;
+ HTREEITEM GetLastVisible() const;
+ HTREEITEM GetNextItem(HTREEITEM hItem, UINT nCode) const;
+ HTREEITEM GetNextSibling(HTREEITEM hItem) const;
+ HTREEITEM GetNextVisible(HTREEITEM hItem) const;
+ HTREEITEM GetParentItem(HTREEITEM hItem) const;
+ HTREEITEM GetPrevSibling(HTREEITEM hItem) const;
+ HTREEITEM GetPrevVisible(HTREEITEM hItem) const;
+ HTREEITEM GetRootItem() const;
+ int GetScrollTime() const;
+ HTREEITEM GetSelection() const;
+ COLORREF GetTextColor() const;
+ HWND GetToolTips() const;
+ UINT GetVisibleCount() const;
+ BOOL ItemHasChildren(HTREEITEM hItem) const;
+ COLORREF SetBkColor(COLORREF clrBk) const;
+ HIMAGELIST SetImageList(HIMAGELIST himl, int nType) const;
+ void SetIndent(int indent) const;
+ BOOL SetInsertMark(HTREEITEM hItem, BOOL fAfter = TRUE) const;
+ COLORREF SetInsertMarkColor(COLORREF clrInsertMark) const;
+ BOOL SetItem(TVITEM& Item) const;
+ BOOL SetItem(HTREEITEM hItem, UINT nMask, LPCTSTR szText, int nImage, int nSelectedImage, UINT nState, UINT nStateMask, LPARAM lParam) const;
+ BOOL SetItemData(HTREEITEM hItem, DWORD_PTR dwData) const;
+ int SetItemHeight(SHORT cyItem) const;
+ BOOL SetItemImage(HTREEITEM hItem, int nImage, int nSelectedImage) const;
+ BOOL SetItemText(HTREEITEM hItem, LPCTSTR szText) const;
+ UINT SetScrollTime(UINT uScrollTime) const;
+ COLORREF SetTextColor(COLORREF clrText) const;
+ HWND SetToolTips(HWND hwndTooltip) const;
+
+// Operations
+ HIMAGELIST CreateDragImage(HTREEITEM hItem) const;
+ BOOL DeleteAllItems() const;
+ BOOL DeleteItem(HTREEITEM hItem) const;
+ HWND EditLabel(HTREEITEM hItem) const;
+ BOOL EndEditLabelNow(BOOL fCancel) const;
+ BOOL EnsureVisible(HTREEITEM hItem) const;
+ BOOL Expand(HTREEITEM hItem, UINT nCode) const;
+ HTREEITEM HitTest(TVHITTESTINFO& ht) const;
+ HTREEITEM InsertItem(TVINSERTSTRUCT& tvIS) const;
+ BOOL Select(HTREEITEM hitem, UINT flag) const;
+ BOOL SelectDropTarget(HTREEITEM hItem) const;
+ BOOL SelectItem(HTREEITEM hItem) const;
+ BOOL SelectSetFirstVisible(HTREEITEM hItem) const;
+ BOOL SortChildren(HTREEITEM hItem, BOOL fRecurse) const;
+ BOOL SortChildrenCB(TVSORTCB& sort, BOOL fRecurse) const;
+
+ private:
+ CTreeView(const CTreeView&); // Disable copy construction
+ CTreeView& operator = (const CTreeView&); // Disable assignment operator
+
+ };
+
+}
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+namespace Win32xx
+{
+
+ inline void CTreeView::PreRegisterClass(WNDCLASS &wc)
+ {
+ // Set the Window Class
+ wc.lpszClassName = WC_TREEVIEW;
+ }
+
+// Attributes
+ inline COLORREF CTreeView::GetBkColor() const
+ // Retrieves the current background color of the control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return TreeView_GetBkColor( m_hWnd );
+ }
+
+ inline HTREEITEM CTreeView::GetChild(HTREEITEM hItem) const
+ // Retrieves the first child item of the specified tree-view item.
+ {
+ assert(::IsWindow(m_hWnd));
+ return TreeView_GetChild(m_hWnd, hItem);
+ }
+
+ inline UINT CTreeView::GetCount() const
+ // Retrieves a count of the items in a tree-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return TreeView_GetCount( m_hWnd );
+ }
+
+ inline HTREEITEM CTreeView::GetDropHiLightItem() const
+ // Retrieves the tree-view item that is the target of a drag-and-drop operation.
+ {
+ assert(::IsWindow(m_hWnd));
+ return TreeView_GetDropHilight(m_hWnd);
+ }
+
+ inline HWND CTreeView::GetEditControl() const
+ // Retrieves the handle to the edit control being used to edit a tree-view item's text.
+ {
+ assert(::IsWindow(m_hWnd));
+ return TreeView_GetEditControl( m_hWnd );
+ }
+
+ inline HTREEITEM CTreeView::GetFirstVisible() const
+ // Retrieves the first visible item in a tree-view control window.
+ {
+ assert(::IsWindow(m_hWnd));
+ return TreeView_GetFirstVisible(m_hWnd);
+ }
+
+ inline HIMAGELIST CTreeView::GetImageList(int iImageType) const
+ // Retrieves the handle to the normal or state image list associated with a tree-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return TreeView_GetImageList( m_hWnd, iImageType );
+ }
+
+ inline UINT CTreeView::GetIndent() const
+ // Retrieves the amount, in pixels, that child items are indented relative to their parent items.
+ {
+ assert(::IsWindow(m_hWnd));
+ return TreeView_GetIndent( m_hWnd );
+ }
+
+ inline COLORREF CTreeView::GetInsertMarkColor() const
+ // Retrieves the color used to draw the insertion mark for the tree view.
+ {
+ assert(::IsWindow(m_hWnd));
+ return TreeView_GetInsertMarkColor( m_hWnd );
+ }
+
+ inline BOOL CTreeView::GetItem(TVITEM& Item) const
+ // Retrieves some or all of a tree-view item's attributes.
+ {
+ assert(::IsWindow(m_hWnd));
+ return TreeView_GetItem( m_hWnd, &Item );
+ }
+
+ inline DWORD_PTR CTreeView::GetItemData(HTREEITEM hItem) const
+ // Retrieves a tree-view item's application data.
+ {
+ assert(::IsWindow(m_hWnd));
+
+ TVITEM tvi = {0};
+ tvi.mask = TVIF_PARAM;
+ tvi.hItem = hItem;
+ TreeView_GetItem( m_hWnd, &tvi );
+ return tvi.lParam;
+ }
+
+ inline int CTreeView::GetItemHeight() const
+ // Retrieves the current height of the tree-view item.
+ {
+ assert(::IsWindow(m_hWnd));
+ return TreeView_GetItemHeight( m_hWnd );
+ }
+
+ inline BOOL CTreeView::GetItemImage(HTREEITEM hItem, int& nImage, int& nSelectedImage ) const
+ // Retrieves the index of the tree-view item's image and selected image.
+ {
+ assert(::IsWindow(m_hWnd));
+
+ TVITEM tvi = {0};
+ tvi.mask = TVIF_IMAGE | TVIF_SELECTEDIMAGE;
+ tvi.hItem = hItem;
+ BOOL bResult = TreeView_GetItem( m_hWnd, &tvi );
+ nImage = tvi.iImage;
+ nSelectedImage = tvi.iSelectedImage;
+ return bResult;
+ }
+
+ inline BOOL CTreeView::GetItemRect(HTREEITEM hItem, CRect& rc, BOOL bTextOnly) const
+ // Retrieves the bounding rectangle for a tree-view item and indicates whether the item is visible.
+ {
+ assert(::IsWindow(m_hWnd));
+ return TreeView_GetItemRect( m_hWnd, hItem, &rc, bTextOnly );
+ }
+
+ inline tString CTreeView::GetItemText(HTREEITEM hItem, UINT nTextMax /* = 260 */) const
+ // Retrieves the text for a tree-view item.
+ // Note: Although the tree-view control allows any length string to be stored
+ // as item text, only the first 260 characters are displayed.
+ {
+ assert(::IsWindow(m_hWnd));
+
+ tString t;
+ if (nTextMax > 0)
+ {
+ TVITEM tvi = {0};
+ tvi.hItem = hItem;
+ tvi.mask = TVIF_TEXT;
+ tvi.cchTextMax = nTextMax;
+ std::vector<TCHAR> vTChar(nTextMax +1, _T('\0'));
+ TCHAR* pTCharArray = &vTChar.front();
+ tvi.pszText = pTCharArray;
+ ::SendMessage(m_hWnd, TVM_GETITEM, 0L, (LPARAM)&tvi);
+ t = tvi.pszText;
+ }
+ return t;
+ }
+
+ inline HTREEITEM CTreeView::GetLastVisible() const
+ // Retrieves the last expanded item in a tree-view control.
+ // This does not retrieve the last item visible in the tree-view window.
+ {
+ assert(::IsWindow(m_hWnd));
+ return TreeView_GetLastVisible(m_hWnd);
+ }
+
+ inline HTREEITEM CTreeView::GetNextItem(HTREEITEM hItem, UINT nCode) const
+ // Retrieves the tree-view item that bears the specified relationship to a specified item.
+ {
+ assert(::IsWindow(m_hWnd));
+ return TreeView_GetNextItem( m_hWnd, hItem, nCode);
+ }
+
+ inline HTREEITEM CTreeView::GetNextSibling(HTREEITEM hItem) const
+ // Retrieves the next sibling item of a specified item in a tree-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return TreeView_GetNextSibling(m_hWnd, hItem);
+ }
+
+ inline HTREEITEM CTreeView::GetNextVisible(HTREEITEM hItem) const
+ // Retrieves the next visible item that follows a specified item in a tree-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return TreeView_GetNextVisible(m_hWnd, hItem);
+ }
+
+ inline HTREEITEM CTreeView::GetParentItem(HTREEITEM hItem) const
+ // Retrieves the parent item of the specified tree-view item.
+ {
+ assert(::IsWindow(m_hWnd));
+ return TreeView_GetParent(m_hWnd, hItem);
+ }
+
+ inline HTREEITEM CTreeView::GetPrevSibling(HTREEITEM hItem) const
+ // Retrieves the previous sibling item of a specified item in a tree-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return TreeView_GetPrevSibling(m_hWnd, hItem);
+ }
+
+ inline HTREEITEM CTreeView::GetPrevVisible(HTREEITEM hItem) const
+ // Retrieves the first visible item that precedes a specified item in a tree-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return TreeView_GetPrevSibling(m_hWnd, hItem);
+ }
+
+ inline HTREEITEM CTreeView::GetRootItem() const
+ // Retrieves the topmost or very first item of the tree-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return TreeView_GetRoot(m_hWnd);
+ }
+
+ inline int CTreeView::GetScrollTime() const
+ // Retrieves the maximum scroll time for the tree-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return TreeView_GetScrollTime( m_hWnd );
+ }
+
+ inline HTREEITEM CTreeView::GetSelection() const
+ // Retrieves the currently selected item in a tree-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return TreeView_GetSelection(m_hWnd);
+ }
+
+ inline COLORREF CTreeView::GetTextColor() const
+ // Retrieves the current text color of the control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return TreeView_GetTextColor( m_hWnd );
+ }
+
+ inline HWND CTreeView::GetToolTips() const
+ // Retrieves the handle to the child ToolTip control used by a tree-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return TreeView_GetToolTips( m_hWnd );
+ }
+
+ inline UINT CTreeView::GetVisibleCount() const
+ // Obtains the number of items that can be fully visible in the client window of a tree-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return TreeView_GetVisibleCount( m_hWnd );
+ }
+
+ inline BOOL CTreeView::ItemHasChildren(HTREEITEM hItem) const
+ // Returns true of the tree-view item has one or more children
+ {
+ assert(::IsWindow(m_hWnd));
+
+ if (TreeView_GetChild( m_hWnd, hItem ))
+ return TRUE;
+
+ return FALSE;
+ }
+
+ inline COLORREF CTreeView::SetBkColor(COLORREF clrBk) const
+ // Sets the background color of the control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return TreeView_SetBkColor( m_hWnd, clrBk );
+ }
+
+ inline HIMAGELIST CTreeView::SetImageList(HIMAGELIST himl, int nType) const
+ // Sets the normal or state image list for a tree-view control
+ // and redraws the control using the new images.
+ {
+ assert(::IsWindow(m_hWnd));
+ return TreeView_SetImageList( m_hWnd, himl, nType );
+ }
+
+ inline void CTreeView::SetIndent(int indent) const
+ // Sets the width of indentation for a tree-view control
+ // and redraws the control to reflect the new width.
+ {
+ assert(::IsWindow(m_hWnd));
+ TreeView_SetIndent( m_hWnd, indent );
+ }
+
+ inline BOOL CTreeView::SetInsertMark(HTREEITEM hItem, BOOL fAfter/* = TRUE*/) const
+ // Sets the insertion mark in a tree-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return TreeView_SetInsertMark( m_hWnd, hItem, fAfter );
+ }
+
+ inline COLORREF CTreeView::SetInsertMarkColor(COLORREF clrInsertMark) const
+ // Sets the color used to draw the insertion mark for the tree view.
+ {
+ assert(::IsWindow(m_hWnd));
+ return TreeView_SetInsertMarkColor( m_hWnd, clrInsertMark );
+ }
+
+ inline BOOL CTreeView::SetItem(TVITEM& Item) const
+ // Sets some or all of a tree-view item's attributes.
+ {
+ assert(::IsWindow(m_hWnd));
+ return TreeView_SetItem( m_hWnd, &Item );
+ }
+
+ inline BOOL CTreeView::SetItem(HTREEITEM hItem, UINT nMask, LPCTSTR szText, int nImage, int nSelectedImage, UINT nState, UINT nStateMask, LPARAM lParam) const
+ // Sets some or all of a tree-view item's attributes.
+ {
+ assert(::IsWindow(m_hWnd));
+
+ TVITEM tvi = {0};
+ tvi.hItem = hItem;
+ tvi.mask = nMask;
+ tvi.pszText = (LPTSTR)szText;
+ tvi.iImage = nImage;
+ tvi.iSelectedImage = nSelectedImage;
+ tvi.state = nState;
+ tvi.stateMask = nStateMask;
+ tvi.lParam = lParam;
+ return TreeView_SetItem( m_hWnd, &tvi );
+ }
+
+ inline BOOL CTreeView::SetItemData(HTREEITEM hItem, DWORD_PTR dwData) const
+ // Sets the tree-view item's application data.
+ {
+ assert(::IsWindow(m_hWnd));
+
+ TVITEM tvi = {0};
+ tvi.hItem = hItem;
+ tvi.mask = TVIF_PARAM;
+ tvi.lParam = dwData;
+ return TreeView_SetItem( m_hWnd, &tvi );
+ }
+
+ inline int CTreeView::SetItemHeight(SHORT cyItem) const
+ // Sets the height of the tree-view items.
+ {
+ assert(::IsWindow(m_hWnd));
+ return TreeView_SetItemHeight( m_hWnd, cyItem );
+ }
+
+ inline BOOL CTreeView::SetItemImage(HTREEITEM hItem, int nImage, int nSelectedImage) const
+ // Sets the tree-view item's application image.
+ {
+ assert(::IsWindow(m_hWnd));
+
+ TVITEM tvi = {0};
+ tvi.hItem = hItem;
+ tvi.iImage = nImage;
+ tvi.iSelectedImage = nSelectedImage;
+ tvi.mask = TVIF_IMAGE | TVIF_SELECTEDIMAGE;
+ return TreeView_SetItem(m_hWnd, &tvi );
+ }
+
+ inline BOOL CTreeView::SetItemText(HTREEITEM hItem, LPCTSTR szText) const
+ // Sets the tree-view item's application text.
+ {
+ assert(::IsWindow(m_hWnd));
+
+ TVITEM tvi = {0};
+ tvi.hItem = hItem;
+ tvi.pszText = (LPTSTR)szText;
+ tvi.mask = TVIF_TEXT;
+ return TreeView_SetItem(m_hWnd, &tvi );
+ }
+
+ inline UINT CTreeView::SetScrollTime(UINT uScrollTime) const
+ // Sets the maximum scroll time for the tree-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return TreeView_SetScrollTime( m_hWnd, uScrollTime );
+ }
+
+ inline COLORREF CTreeView::SetTextColor(COLORREF clrText) const
+ // Sets the text color of the control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return TreeView_SetTextColor( m_hWnd, clrText );
+ }
+
+ inline HWND CTreeView::SetToolTips(HWND hwndTooltip) const
+ // Sets a tree-view control's child ToolTip control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return TreeView_SetToolTips( m_hWnd, hwndTooltip );
+ }
+
+ // Operations
+
+ inline HIMAGELIST CTreeView::CreateDragImage(HTREEITEM hItem) const
+ // Creates a dragging bitmap for the specified item in a tree-view control.
+ // It also creates an image list for the bitmap and adds the bitmap to the image list.
+ // An application can display the image when dragging the item by using the image list functions.
+ {
+ assert(::IsWindow(m_hWnd));
+ return TreeView_CreateDragImage( m_hWnd, hItem );
+ }
+
+ inline BOOL CTreeView::DeleteAllItems() const
+ // Deletes all items from a tree-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return TreeView_DeleteAllItems( m_hWnd );
+ }
+
+ inline BOOL CTreeView::DeleteItem(HTREEITEM hItem) const
+ // Removes an item and all its children from a tree-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return TreeView_DeleteItem( m_hWnd, hItem );
+ }
+
+ inline HWND CTreeView::EditLabel(HTREEITEM hItem) const
+ // Begins in-place editing of the specified item's text, replacing the text of the item
+ // with a single-line edit control containing the text.
+ // The specified item is implicitly selected and focused.
+ {
+ assert(::IsWindow(m_hWnd));
+ return TreeView_EditLabel( m_hWnd, hItem );
+ }
+
+ inline BOOL CTreeView::EndEditLabelNow(BOOL fCancel) const
+ // Ends the editing of a tree-view item's label.
+ {
+ assert(::IsWindow(m_hWnd));
+ return TreeView_EndEditLabelNow(m_hWnd, fCancel);
+ }
+
+ inline BOOL CTreeView::EnsureVisible(HTREEITEM hItem) const
+ // Ensures that a tree-view item is visible, expanding the parent item or
+ // scrolling the tree-view control, if necessary.
+ {
+ assert(::IsWindow(m_hWnd));
+ return TreeView_EnsureVisible( m_hWnd, hItem );
+ }
+
+ inline BOOL CTreeView::Expand(HTREEITEM hItem, UINT nCode) const
+ // The TreeView_Expand macro expands or collapses the list of child items associated
+ // with the specified parent item, if any.
+ {
+ assert(::IsWindow(m_hWnd));
+ return TreeView_Expand( m_hWnd, hItem, nCode );
+ }
+
+ inline HTREEITEM CTreeView::HitTest(TVHITTESTINFO& ht) const
+ // Determines the location of the specified point relative to the client area of a tree-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return TreeView_HitTest( m_hWnd, &ht );
+ }
+
+ inline HTREEITEM CTreeView::InsertItem(TVINSERTSTRUCT& tvIS) const
+ // Inserts a new item in a tree-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return TreeView_InsertItem( m_hWnd, &tvIS );
+ }
+
+ inline BOOL CTreeView::Select(HTREEITEM hitem, UINT flag) const
+ // Selects the specified tree-view item, scrolls the item into view, or redraws
+ // the item in the style used to indicate the target of a drag-and-drop operation.
+ {
+ assert(::IsWindow(m_hWnd));
+ return TreeView_Select(m_hWnd, hitem, flag );
+ }
+
+ inline BOOL CTreeView::SelectDropTarget(HTREEITEM hItem) const
+ // Redraws a specified tree-view control item in the style used to indicate the
+ // target of a drag-and-drop operation.
+ {
+ assert(::IsWindow(m_hWnd));
+ return TreeView_SelectDropTarget(m_hWnd, hItem);
+ }
+
+ inline BOOL CTreeView::SelectItem(HTREEITEM hItem) const
+ // Selects the specified tree-view item.
+ {
+ assert(::IsWindow(m_hWnd));
+ return TreeView_SelectItem(m_hWnd, hItem);
+ }
+
+ inline BOOL CTreeView::SelectSetFirstVisible(HTREEITEM hItem) const
+ // Scrolls the tree-view control vertically to ensure that the specified item is visible.
+ // If possible, the specified item becomes the first visible item at the top of the control's window.
+ {
+ assert(::IsWindow(m_hWnd));
+ return TreeView_SelectSetFirstVisible(m_hWnd, hItem);
+ }
+
+ inline BOOL CTreeView::SortChildren(HTREEITEM hItem, BOOL fRecurse) const
+ // Sorts the child items of the specified parent item in a tree-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return TreeView_SortChildren( m_hWnd, hItem, fRecurse );
+ }
+
+ inline BOOL CTreeView::SortChildrenCB(TVSORTCB& sort, BOOL fRecurse) const
+ // Sorts tree-view items using an application-defined callback function that compares the items.
+ {
+ assert(::IsWindow(m_hWnd));
+ return TreeView_SortChildrenCB( m_hWnd, &sort, fRecurse );
+ }
+
+
+} // namespace Win32xx
+
+#endif // #ifndef _WIN32XX_TREEVIEW_H_
+
diff --git a/mmc_updater/depends/win32cpp/wceframe.h b/mmc_updater/depends/win32cpp/wceframe.h
new file mode 100644
index 00000000..f3aa67ef
--- /dev/null
+++ b/mmc_updater/depends/win32cpp/wceframe.h
@@ -0,0 +1,420 @@
+// Win32++ Version 7.2
+// Released: 5th AUgust 2011
+//
+// David Nash
+// email: dnash@bigpond.net.au
+// url: https://sourceforge.net/projects/win32-framework
+//
+//
+// Copyright (c) 2005-2011 David Nash
+//
+// Permission is hereby granted, free of charge, to
+// any person obtaining a copy of this software and
+// associated documentation files (the "Software"),
+// to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify,
+// merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom
+// the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice
+// shall be included in all copies or substantial portions
+// of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
+// OR OTHER DEALINGS IN THE SOFTWARE.
+//
+////////////////////////////////////////////////////////
+
+
+//////////////////////////////////////////////////////
+// WceFrame.h
+// Definitions for the CCmdBar and CWceFrame
+
+// These classes are provide a frame window for use on Window CE devices such
+// as Pocket PCs. The frame uses CommandBar (a control unique to the Windows CE
+// operating systems) to display the menu and toolbar.
+//
+// Use the PocketPCWceFrame generic application as the starting point for your own
+// frame based applications on the Pocket PC.
+//
+// Refer to the Scribble demo application for an example of how these classes
+// can be used.
+
+
+#ifndef _WIN32XX_WCEFRAME_H_
+#define _WIN32XX_WCEFRAME_H_
+
+
+#include "wincore.h"
+#include <commctrl.h>
+#include <vector>
+#include "default_resource.h"
+
+#if defined(WIN32_PLATFORM_PSPC) || defined(WIN32_PLATFORM_WFSP)
+ #define SHELL_AYGSHELL
+#endif
+
+#ifdef SHELL_AYGSHELL
+ #include <aygshell.h>
+ #pragma comment(lib, "aygshell.lib")
+#endif // SHELL_AYGSHELL
+
+#if (_WIN32_WCE < 0x500 && defined(SHELL_AYGSHELL)) || _WIN32_WCE == 420
+ #pragma comment(lib, "ccrtrtti.lib")
+#endif
+
+
+namespace Win32xx
+{
+
+ ////////////////////////////////////
+ // Declaration of the CCmdBar class
+ //
+ class CCmdBar : public CWnd
+ {
+ public:
+ CCmdBar();
+ virtual ~CCmdBar();
+ virtual BOOL AddAdornments(DWORD dwFlags);
+ virtual int AddBitmap(int idBitmap, int iNumImages, int iImageWidth, int iImageHeight);
+ virtual BOOL AddButtons(int nButtons, TBBUTTON* pTBButton);
+ virtual HWND Create(HWND hwndParent);
+ virtual int GetHeight() const;
+ virtual HWND InsertComboBox(int iWidth, UINT dwStyle, WORD idComboBox, WORD iButton);
+ virtual BOOL IsVisible();
+ virtual BOOL Show(BOOL fShow);
+
+ private:
+
+#ifdef SHELL_AYGSHELL
+ SHMENUBARINFO m_mbi;
+#endif
+
+ };
+
+
+ //////////////////////////////////////
+ // Declaration of the CWceFrame class
+ // A mini frame based on CCmdBar
+ class CWceFrame : public CWnd
+ {
+ public:
+ CWceFrame();
+ virtual ~CWceFrame();
+ virtual void AddToolBarButton(UINT nID);
+ CRect GetViewRect() const;
+ CCmdBar& GetMenuBar() const {return (CCmdBar&)m_MenuBar;}
+ virtual void OnActivate(WPARAM wParam, LPARAM lParam);
+ virtual void OnCreate();
+ virtual void PreCreate(CREATESTRUCT &cs);
+ virtual void RecalcLayout();
+ virtual void SetButtons(const std::vector<UINT> ToolBarData);
+ virtual LRESULT WndProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam);
+
+ protected:
+ std::vector<UINT> m_ToolBarData;
+
+ private:
+ CCmdBar m_MenuBar;
+ tString m_tsAppName;
+
+#ifdef SHELL_AYGSHELL
+ SHACTIVATEINFO m_sai;
+#endif
+
+ };
+
+ //////////////////////////////////////////
+ // Definitions for the CCmdBar class
+ // This class wraps CommandBar_Create which
+ // creates a CommandBar at the top of the window
+ inline CCmdBar::CCmdBar()
+ {
+ }
+
+ inline CCmdBar::~CCmdBar()
+ {
+ if (IsWindow())
+ ::CommandBar_Destroy(m_hWnd);
+ }
+
+
+ inline BOOL CCmdBar::AddAdornments(DWORD dwFlags)
+ {
+ BOOL bReturn = CommandBar_AddAdornments(m_hWnd, dwFlags, 0);
+
+ if (!bReturn)
+ throw CWinException(_T("AddAdornments failed"));
+
+ return bReturn;
+ }
+
+ inline int CCmdBar::AddBitmap(int idBitmap, int iNumImages, int iImageWidth, int iImageHeight)
+ {
+ HINSTANCE hInst = GetApp()->GetInstanceHandle();
+ return CommandBar_AddBitmap(m_hWnd, hInst, idBitmap, iNumImages, iImageWidth, iImageHeight);
+ }
+
+ inline BOOL CCmdBar::AddButtons(int nButtons, TBBUTTON* pTBButton)
+ {
+ BOOL bReturn = CommandBar_AddButtons(m_hWnd, nButtons, pTBButton);
+ if (!bReturn)
+ throw CWinException(_T("Failed to add buttons to commandbar"));
+
+ return bReturn;
+ }
+
+ inline HWND CCmdBar::Create(HWND hParent)
+ {
+#ifdef SHELL_AYGSHELL
+ SHMENUBARINFO mbi;
+
+ memset(&mbi, 0, sizeof(SHMENUBARINFO));
+ mbi.cbSize = sizeof(SHMENUBARINFO);
+ mbi.hwndParent = hParent;
+ mbi.nToolBarId = IDW_MAIN;
+ mbi.hInstRes = GetApp()->GetInstanceHandle();
+ mbi.nBmpId = 0;
+ mbi.cBmpImages = 0;
+
+ if (SHCreateMenuBar(&mbi))
+ {
+ m_hWnd = mbi.hwndMB;
+ }
+ else
+ throw CWinException(_T("Failed to create MenuBar"));
+
+#else
+ m_hWnd = CommandBar_Create(GetApp()->GetInstanceHandle(), hParent, IDW_MENUBAR);
+
+ if (m_hWnd == NULL)
+ throw CWinException(_T("Failed to create CommandBar"));
+
+ CommandBar_InsertMenubar(m_hWnd, GetApp()->GetInstanceHandle(), IDW_MAIN, 0);
+#endif
+ return m_hWnd;
+ }
+
+ inline int CCmdBar::GetHeight() const
+ {
+ return CommandBar_Height(m_hWnd);
+ }
+
+ inline HWND CCmdBar::InsertComboBox(int iWidth, UINT dwStyle, WORD idComboBox, WORD iButton)
+ {
+ HINSTANCE hInst = GetApp()->GetInstanceHandle();
+ HWND hWnd = CommandBar_InsertComboBox(m_hWnd, hInst, iWidth, dwStyle, idComboBox, iButton);
+
+ if (!hWnd)
+ throw CWinException(_T("InsertComboBox failed"));
+
+ return hWnd;
+ }
+
+ inline BOOL CCmdBar::IsVisible()
+ {
+ return ::CommandBar_IsVisible(m_hWnd);
+ }
+
+ inline BOOL CCmdBar::Show(BOOL fShow)
+ {
+ return ::CommandBar_Show(m_hWnd, fShow);
+ }
+
+
+ /////////////////////////////////////////
+ // Definitions for the CWceFrame class
+ // This class creates a simple frame using CCmdBar
+ inline CWceFrame::CWceFrame()
+ {
+#ifdef SHELL_AYGSHELL
+ // Initialize the shell activate info structure
+ memset (&m_sai, 0, sizeof (m_sai));
+ m_sai.cbSize = sizeof (m_sai);
+#endif
+ }
+
+ inline CWceFrame::~CWceFrame()
+ {
+ }
+
+ inline void CWceFrame::AddToolBarButton(UINT nID)
+ // Adds Resource IDs to toolbar buttons.
+ // A resource ID of 0 is a separator
+ {
+ m_ToolBarData.push_back(nID);
+ }
+
+ inline CRect CWceFrame::GetViewRect() const
+ {
+ CRect r;
+ ::GetClientRect(m_hWnd, &r);
+
+#ifndef SHELL_AYGSHELL
+ // Reduce the size of the client rectange, by the commandbar height
+ r.top += m_MenuBar.GetHeight();
+#endif
+
+ return r;
+ }
+
+ inline void CWceFrame::OnCreate()
+ {
+ // Create the Commandbar
+ m_MenuBar.Create(m_hWnd);
+
+ // Set the keyboard accelerators
+ HACCEL hAccel = LoadAccelerators(GetApp()->GetResourceHandle(), MAKEINTRESOURCE(IDW_MAIN));
+ GetApp()->SetAccelerators(hAccel, this);
+
+ // Add the toolbar buttons
+ if (m_ToolBarData.size() > 0)
+ SetButtons(m_ToolBarData);
+
+#ifndef SHELL_AYGSHELL
+ // Add close button
+ m_MenuBar.AddAdornments(0);
+#endif
+
+ }
+
+ inline void CWceFrame::OnActivate(WPARAM wParam, LPARAM lParam)
+ {
+#ifdef SHELL_AYGSHELL
+ // Notify shell of our activate message
+ SHHandleWMActivate(m_hWnd, wParam, lParam, &m_sai, FALSE);
+
+ UINT fActive = LOWORD(wParam);
+ if ((fActive == WA_ACTIVE) || (fActive == WA_CLICKACTIVE))
+ {
+ // Reposition the window when it's activated
+ RecalcLayout();
+ }
+#endif
+ }
+
+ inline void CWceFrame::PreCreate(CREATESTRUCT &cs)
+ {
+ cs.style = WS_VISIBLE;
+ m_tsAppName = _T("Win32++ Application");
+
+ // Choose a unique class name for this app
+ if (LoadString(IDW_MAIN) != _T(""))
+ {
+ m_tsAppName = LoadString(IDW_MAIN);
+ }
+
+ cs.lpszClass = m_tsAppName.c_str();
+ }
+
+/* inline BOOL CWceFrame::PreTranslateMessage(MSG* pMsg)
+ {
+ HACCEL hAccelTable = ::LoadAccelerators(GetApp()->GetResourceHandle(), MAKEINTRESOURCE(IDW_MAIN));
+ if (WM_KEYFIRST <= pMsg->message && pMsg->message <= WM_KEYLAST)
+ {
+ if (TranslateAccelerator(m_hWnd, hAccelTable, pMsg))
+ return TRUE;
+ }
+ return CWnd::PreTranslateMessage(pMsg);
+ } */
+
+ inline void CWceFrame::RecalcLayout()
+ {
+ HWND hwndCB = m_MenuBar.GetHwnd();
+ if (hwndCB)
+ {
+ CRect rc; // Desktop window size
+ CRect rcMenuBar; // MenuBar window size
+
+ ::SystemParametersInfo(SPI_GETWORKAREA, 0, &rc, 0);
+ ::GetWindowRect(hwndCB, &rcMenuBar);
+ rc.bottom -= (rcMenuBar.bottom - rcMenuBar.top);
+
+ MoveWindow(rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top, FALSE);
+ }
+
+ ShowWindow(TRUE);
+ UpdateWindow();
+ }
+
+ inline void CWceFrame::SetButtons(const std::vector<UINT> ToolBarData)
+ // Define the resource IDs for the toolbar like this in the Frame's constructor
+ // m_ToolBarData.push_back ( 0 ); // Separator
+ // m_ToolBarData.clear();
+ // m_ToolBarData.push_back ( IDM_FILE_NEW );
+ // m_ToolBarData.push_back ( IDM_FILE_OPEN );
+ // m_ToolBarData.push_back ( IDM_FILE_SAVE );
+
+ {
+ int iImages = 0;
+ int iNumButtons = (int)ToolBarData.size();
+
+
+ if (iNumButtons > 0)
+ {
+ // Create the TBBUTTON array for each button
+ std::vector<TBBUTTON> vTBB(iNumButtons);
+ TBBUTTON* tbbArray = &vTBB.front();
+
+ for (int j = 0 ; j < iNumButtons; j++)
+ {
+ ZeroMemory(&tbbArray[j], sizeof(TBBUTTON));
+
+ if (ToolBarData[j] == 0)
+ {
+ tbbArray[j].fsStyle = TBSTYLE_SEP;
+ }
+ else
+ {
+ tbbArray[j].iBitmap = iImages++;
+ tbbArray[j].idCommand = ToolBarData[j];
+ tbbArray[j].fsState = TBSTATE_ENABLED;
+ tbbArray[j].fsStyle = TBSTYLE_BUTTON;
+ tbbArray[j].iString = -1;
+ }
+ }
+
+ // Add the bitmap
+ GetMenuBar().AddBitmap(IDW_MAIN, iImages , 16, 16);
+
+ // Add the buttons
+ GetMenuBar().AddButtons(iNumButtons, tbbArray);
+ }
+ }
+
+ inline LRESULT CWceFrame::WndProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam)
+ {
+ switch (uMsg)
+ {
+ case WM_DESTROY:
+ PostQuitMessage(0);
+ break;
+ case WM_ACTIVATE:
+ OnActivate(wParam, lParam);
+ break;
+
+#ifdef SHELL_AYGSHELL
+
+ case WM_SETTINGCHANGE:
+ SHHandleWMSettingChange(m_hWnd, wParam, lParam, &m_sai);
+ break;
+#endif
+
+ }
+ return CWnd::WndProcDefault(uMsg, wParam, lParam);
+ }
+
+
+} // namespace Win32xx
+
+#endif // _WIN32XX_WCEFRAME_H_
+
diff --git a/mmc_updater/depends/win32cpp/wcestddef.h b/mmc_updater/depends/win32cpp/wcestddef.h
new file mode 100644
index 00000000..f7b22833
--- /dev/null
+++ b/mmc_updater/depends/win32cpp/wcestddef.h
@@ -0,0 +1,58 @@
+
+#pragma once
+
+#pragma comment(linker, "/nodefaultlib:libc.lib")
+#pragma comment(linker, "/nodefaultlib:libcd.lib")
+
+
+#include <ceconfig.h>
+#if defined(WIN32_PLATFORM_PSPC) || defined(WIN32_PLATFORM_WFSP)
+ #define SHELL_AYGSHELL
+#endif
+
+#ifdef _CE_DCOM
+ #define _ATL_APARTMENT_THREADED
+#endif
+
+#if defined(WIN32_PLATFORM_PSPC) || defined(WIN32_PLATFORM_WFSP)
+ #ifndef _DEVICE_RESOLUTION_AWARE
+ #define _DEVICE_RESOLUTION_AWARE
+ #endif
+#endif
+
+
+#if _WIN32_WCE == 420 || _WIN32_WCE == 0x420
+ // For Pocket PC 2003
+ #pragma comment(lib, "ccrtrtti.lib")
+#endif
+
+#if _MSC_VER >= 1300
+
+ // NOTE - this value is not strongly correlated to the Windows CE OS version being targeted
+ #undef WINVER
+ #define WINVER _WIN32_WCE
+
+ #ifdef _DEVICE_RESOLUTION_AWARE
+ #include "DeviceResolutionAware.h"
+ #endif
+
+ #if _WIN32_WCE < 0x500 && ( defined(WIN32_PLATFORM_PSPC) || defined(WIN32_PLATFORM_WFSP) )
+ #ifdef _X86_
+ #if defined(_DEBUG)
+ #pragma comment(lib, "libcmtx86d.lib")
+ #else
+ #pragma comment(lib, "libcmtx86.lib")
+ #endif
+ #endif
+ #endif
+
+ #include <altcecrt.h>
+
+#endif// _MSC_VER >= 1300
+
+#ifdef SHELL_AYGSHELL
+ #include <aygshell.h>
+ #pragma comment(lib, "aygshell.lib")
+#endif // SHELL_AYGSHELL
+
+// TODO: reference additional headers your program requires here
diff --git a/mmc_updater/depends/win32cpp/webbrowser.h b/mmc_updater/depends/win32cpp/webbrowser.h
new file mode 100644
index 00000000..5a5b5f41
--- /dev/null
+++ b/mmc_updater/depends/win32cpp/webbrowser.h
@@ -0,0 +1,760 @@
+// Win32++ Version 7.2
+// Released: 5th AUgust 2011
+//
+// David Nash
+// email: dnash@bigpond.net.au
+// url: https://sourceforge.net/projects/win32-framework
+//
+//
+// Copyright (c) 2005-2011 David Nash
+//
+// Permission is hereby granted, free of charge, to
+// any person obtaining a copy of this software and
+// associated documentation files (the "Software"),
+// to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify,
+// merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom
+// the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice
+// shall be included in all copies or substantial portions
+// of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
+// OR OTHER DEALINGS IN THE SOFTWARE.
+//
+////////////////////////////////////////////////////////
+
+#ifndef _WIN32XX_WEBBROWSER_H_
+#define _WIN32XX_WEBBROWSER_H_
+
+#include <exdisp.h>
+#include <ocidl.h>
+
+
+namespace Win32xx
+{
+ ///////////////////////////////////////////////////
+ // Declaration of the CAXWindow class
+ // This class implements an ActiveX control container
+ class CAXWindow : public IOleClientSite, public IOleInPlaceSite, public IOleInPlaceFrame,
+ public IOleControlSite, public IDispatch
+ {
+ public:
+ CAXWindow();
+ virtual ~CAXWindow();
+ virtual void Activate(BOOL fFocus);
+ virtual void CreateControl(BSTR bstrClsid);
+ virtual void CreateControl(CLSID clsid);
+ virtual void Remove();
+ virtual void SetParent(HWND hWndParent);
+ virtual void SetLocation(int x, int y, int width, int height);
+ virtual void SetVisible(BOOL fVisible);
+ virtual void SetStatusWindow(HWND hWndStatus);
+ virtual void TranslateKey(MSG msg);
+ IDispatch* GetDispatch();
+ IUnknown* GetUnknown();
+
+ // IUnknown Methods
+ STDMETHODIMP QueryInterface(REFIID riid, void** ppvObject);
+ STDMETHODIMP_(ULONG) AddRef();
+ STDMETHODIMP_(ULONG) Release();
+
+ // IOleClientSite Methods
+ STDMETHODIMP SaveObject();
+ STDMETHODIMP GetMoniker(DWORD dwAssign, DWORD dwWhichMoniker, LPMONIKER* ppMk);
+ STDMETHODIMP GetContainer(LPOLECONTAINER* ppContainer);
+ STDMETHODIMP ShowObject();
+ STDMETHODIMP OnShowWindow(BOOL fShow);
+ STDMETHODIMP RequestNewObjectLayout();
+
+ // IOleWindow Methods
+ STDMETHODIMP GetWindow(HWND* phwnd);
+ STDMETHODIMP ContextSensitiveHelp(BOOL fEnterMode);
+
+ // IOleInPlaceSite Methods
+ STDMETHODIMP CanInPlaceActivate();
+ STDMETHODIMP OnInPlaceActivate();
+ STDMETHODIMP OnUIActivate();
+ STDMETHODIMP GetWindowContext(IOleInPlaceFrame** ppFrame, IOleInPlaceUIWindow** ppDoc, LPRECT lprcPosRect, LPRECT lprcClipRect, LPOLEINPLACEFRAMEINFO lpFrameInfo);
+ STDMETHODIMP Scroll(SIZE scrollExtent);
+ STDMETHODIMP OnUIDeactivate(BOOL fUndoable);
+ STDMETHODIMP OnInPlaceDeactivate();
+ STDMETHODIMP DiscardUndoState();
+ STDMETHODIMP DeactivateAndUndo();
+ STDMETHODIMP OnPosRectChange(LPCRECT lprcPosRect);
+
+ // IOleInPlaceUIWindow Methods
+ STDMETHODIMP GetBorder(LPRECT lprectBorder);
+ STDMETHODIMP RequestBorderSpace(LPCBORDERWIDTHS lpborderwidths);
+ STDMETHODIMP SetBorderSpace(LPCBORDERWIDTHS lpborderwidths);
+ STDMETHODIMP SetActiveObject(IOleInPlaceActiveObject* pActiveObject, LPCOLESTR lpszObjName);
+
+ // IOleInPlaceFrame Methods
+ STDMETHODIMP InsertMenus(HMENU hmenuShared, LPOLEMENUGROUPWIDTHS lpMenuWidths);
+ STDMETHODIMP SetMenu(HMENU hmenuShared, HOLEMENU holemenu, HWND hwndActiveObject);
+ STDMETHODIMP RemoveMenus(HMENU hmenuShared);
+ STDMETHODIMP SetStatusText(LPCOLESTR pszStatusText);
+ STDMETHODIMP EnableModeless(BOOL fEnable);
+ STDMETHODIMP TranslateAccelerator(LPMSG lpmsg, WORD wID);
+
+ // IOleControlSite Methods
+ STDMETHODIMP OnControlInfoChanged();
+ STDMETHODIMP LockInPlaceActive(BOOL fLock);
+ STDMETHODIMP GetExtendedControl(IDispatch** ppDisp);
+ STDMETHODIMP TransformCoords(POINTL* pptlHimetric, POINTF* pptfContainer, DWORD dwFlags);
+ STDMETHODIMP TranslateAccelerator(LPMSG pMsg, DWORD grfModifiers);
+ STDMETHODIMP OnFocus(BOOL fGotFocus);
+ STDMETHODIMP ShowPropertyFrame();
+
+ // IDispatch Methods
+ STDMETHODIMP GetIDsOfNames(REFIID riid, OLECHAR** rgszNames, unsigned int cNames, LCID lcid, DISPID* rgdispid);
+ STDMETHODIMP GetTypeInfo(unsigned int itinfo, LCID lcid, ITypeInfo** pptinfo);
+ STDMETHODIMP GetTypeInfoCount(unsigned int* pctinfo);
+ STDMETHODIMP Invoke(DISPID dispid, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS* pdispparams, VARIANT* pvarResult, EXCEPINFO* pexecinfo, unsigned int* puArgErr);
+
+ private:
+ ULONG m_cRefs; // ref count
+ HWND m_hWnd; // window handle of the container
+ HWND m_hWndStatus; // status window handle
+ IUnknown* m_pUnk; // IUnknown of contained object
+ CRect m_rcControl; // size of control
+ };
+
+
+ ///////////////////////////////////////////////
+ // Declaration of the CWebBrowser class
+ // This class uses an AciveX Container provided by
+ // CAXWindow to host the IWebBrower2 interface.
+ class CWebBrowser : public CWnd
+ {
+ public:
+ CWebBrowser();
+ virtual ~CWebBrowser();
+ virtual void AddWebBrowserControl(void);
+ virtual CAXWindow& GetAXWindow() const { return (CAXWindow&)m_AXContainer; }
+ virtual IWebBrowser2* GetIWebBrowser2() const { return m_pIWebBrowser2; }
+ virtual void Navigate(LPCTSTR str);
+
+ protected:
+ virtual void OnCreate();
+ virtual void OnSize(int width, int height);
+ virtual LRESULT WndProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam);
+
+ private:
+ CAXWindow m_AXContainer; // The ActiveX Container
+ IWebBrowser2* m_pIWebBrowser2;// Interface to the ActiveX web browser control
+ };
+
+}
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+namespace Win32xx
+{
+ /////////////////////////////////////////
+ // Definitions for the CAXWindow class
+ //
+ inline CAXWindow::CAXWindow() : m_cRefs(1), m_hWnd(NULL), m_pUnk(NULL)
+ {
+ }
+
+ inline CAXWindow::~CAXWindow()
+ {
+ }
+
+ inline void CAXWindow::CreateControl(BSTR bstrClsid)
+ {
+ CLSID clsid;
+ CLSIDFromString(bstrClsid, &clsid);
+ CreateControl(clsid);
+ }
+
+ inline void CAXWindow::Activate(BOOL fFocus)
+ {
+ if (!m_pUnk)
+ return;
+
+ if (fFocus)
+ {
+ IOleObject* pioo;
+ HRESULT hr = m_pUnk->QueryInterface(IID_IOleObject, (void**)&pioo);
+ if (FAILED(hr))
+ return;
+
+ pioo->DoVerb(OLEIVERB_UIACTIVATE, NULL, this, 0, m_hWnd, &m_rcControl);
+ pioo->Release();
+ }
+ }
+
+ inline void CAXWindow::CreateControl(CLSID clsid)
+ {
+ CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER, IID_IUnknown, (void**)&m_pUnk);
+
+ if (!m_pUnk)
+ return;
+
+ IOleObject* pioo;
+ HRESULT hr = m_pUnk->QueryInterface(IID_IOleObject, (void**)&pioo);
+ if (FAILED(hr))
+ return;
+
+ pioo->SetClientSite(this);
+ pioo->Release();
+
+ IPersistStreamInit* ppsi;
+ hr = m_pUnk->QueryInterface(IID_IPersistStreamInit, (void**)&ppsi);
+ if (SUCCEEDED(hr))
+ {
+ ppsi->InitNew();
+ ppsi->Release();
+ }
+ }
+
+ inline STDMETHODIMP_(ULONG) CAXWindow::AddRef()
+ {
+ return ++m_cRefs;
+ }
+
+ inline STDMETHODIMP CAXWindow::CanInPlaceActivate()
+ {
+ return S_OK;
+ }
+
+ inline STDMETHODIMP CAXWindow::ContextSensitiveHelp(BOOL fEnterMode)
+ {
+ UNREFERENCED_PARAMETER(fEnterMode);
+ return E_NOTIMPL;
+ }
+
+ inline STDMETHODIMP CAXWindow::DeactivateAndUndo()
+ {
+ return E_NOTIMPL;
+ }
+
+ inline STDMETHODIMP CAXWindow::DiscardUndoState()
+ {
+ return E_NOTIMPL;
+ }
+
+ inline STDMETHODIMP CAXWindow::EnableModeless(BOOL fEnable)
+ {
+ UNREFERENCED_PARAMETER(fEnable);
+ return E_NOTIMPL;
+ }
+
+ inline STDMETHODIMP CAXWindow::GetBorder(LPRECT lprectBorder)
+ {
+ UNREFERENCED_PARAMETER(lprectBorder);
+ return E_NOTIMPL;
+ }
+
+ inline STDMETHODIMP CAXWindow::GetContainer(LPOLECONTAINER* ppContainer)
+ {
+ UNREFERENCED_PARAMETER(ppContainer);
+ return E_NOINTERFACE;
+ }
+
+ inline IDispatch* CAXWindow::GetDispatch()
+ {
+ if (!m_pUnk)
+ return NULL;
+
+ HRESULT hr;
+ IDispatch* pdisp;
+
+ hr = m_pUnk->QueryInterface(IID_IDispatch, (void**)&pdisp);
+ return pdisp;
+ }
+
+ inline STDMETHODIMP CAXWindow::GetExtendedControl(IDispatch** ppDisp)
+ {
+ if (ppDisp == NULL)
+ return E_INVALIDARG;
+
+ *ppDisp = (IDispatch*)this;
+ (*ppDisp)->AddRef();
+
+ return S_OK;
+ }
+
+ inline STDMETHODIMP CAXWindow::GetIDsOfNames(REFIID riid, OLECHAR** rgszNames, unsigned int cNames, LCID lcid, DISPID* rgdispid)
+ {
+ UNREFERENCED_PARAMETER((IID)riid); // IID cast required for the MinGW compiler
+ UNREFERENCED_PARAMETER(rgszNames);
+ UNREFERENCED_PARAMETER(cNames);
+ UNREFERENCED_PARAMETER(lcid);
+
+ *rgdispid = DISPID_UNKNOWN;
+ return DISP_E_UNKNOWNNAME;
+ }
+
+ inline STDMETHODIMP CAXWindow::GetMoniker(DWORD dwAssign, DWORD dwWhichMoniker, LPMONIKER* ppMk)
+ {
+ UNREFERENCED_PARAMETER(dwAssign);
+ UNREFERENCED_PARAMETER(dwWhichMoniker);
+ UNREFERENCED_PARAMETER(ppMk);
+ return E_NOTIMPL;
+ }
+
+ inline STDMETHODIMP CAXWindow::GetTypeInfo(unsigned int itinfo, LCID lcid, ITypeInfo** pptinfo)
+ {
+ UNREFERENCED_PARAMETER(itinfo);
+ UNREFERENCED_PARAMETER(lcid);
+ UNREFERENCED_PARAMETER(pptinfo);
+ return E_NOTIMPL;
+ }
+
+ inline STDMETHODIMP CAXWindow::GetTypeInfoCount(unsigned int* pctinfo)
+ {
+ UNREFERENCED_PARAMETER(pctinfo);
+ return E_NOTIMPL;
+ }
+
+ inline IUnknown* CAXWindow::GetUnknown()
+ {
+ if (!m_pUnk)
+ return NULL;
+
+ m_pUnk->AddRef();
+ return m_pUnk;
+ }
+
+ inline STDMETHODIMP CAXWindow::GetWindow(HWND* lphwnd)
+ {
+ if (!IsWindow(m_hWnd))
+ return S_FALSE;
+
+ *lphwnd = m_hWnd;
+ return S_OK;
+ }
+
+ inline STDMETHODIMP CAXWindow::GetWindowContext (IOleInPlaceFrame** ppFrame, IOleInPlaceUIWindow** ppIIPUIWin,
+ LPRECT lprcPosRect, LPRECT lprcClipRect, LPOLEINPLACEFRAMEINFO lpFrameInfo)
+ {
+ *ppFrame = (IOleInPlaceFrame*)this;
+ *ppIIPUIWin = NULL;
+
+ RECT rect;
+ GetClientRect(m_hWnd, &rect);
+ lprcPosRect->left = 0;
+ lprcPosRect->top = 0;
+ lprcPosRect->right = rect.right;
+ lprcPosRect->bottom = rect.bottom;
+
+ CopyRect(lprcClipRect, lprcPosRect);
+
+ lpFrameInfo->cb = sizeof(OLEINPLACEFRAMEINFO);
+ lpFrameInfo->fMDIApp = FALSE;
+ lpFrameInfo->hwndFrame = m_hWnd;
+ lpFrameInfo->haccel = 0;
+ lpFrameInfo->cAccelEntries = 0;
+
+ (*ppFrame)->AddRef();
+ return S_OK;
+ }
+
+ inline STDMETHODIMP CAXWindow::InsertMenus(HMENU hmenuShared, LPOLEMENUGROUPWIDTHS lpMenuWidths)
+ {
+ UNREFERENCED_PARAMETER(hmenuShared);
+ UNREFERENCED_PARAMETER(lpMenuWidths);
+ return E_NOTIMPL;
+ }
+
+ inline STDMETHODIMP CAXWindow::Invoke(DISPID dispid, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS* pdispparams, VARIANT* pvarResult, EXCEPINFO* pexecinfo, unsigned int* puArgErr)
+ {
+ UNREFERENCED_PARAMETER(dispid);
+ UNREFERENCED_PARAMETER((IID)riid); // IID cast required for the MinGW compiler
+ UNREFERENCED_PARAMETER(lcid);
+ UNREFERENCED_PARAMETER(wFlags);
+ UNREFERENCED_PARAMETER(pdispparams);
+ UNREFERENCED_PARAMETER(pvarResult);
+ UNREFERENCED_PARAMETER(pexecinfo);
+ UNREFERENCED_PARAMETER(puArgErr);
+ return DISP_E_MEMBERNOTFOUND;
+ }
+
+ inline STDMETHODIMP CAXWindow::LockInPlaceActive(BOOL fLock)
+ {
+ UNREFERENCED_PARAMETER(fLock);
+ return E_NOTIMPL;
+ }
+
+ inline STDMETHODIMP CAXWindow::OnControlInfoChanged()
+ {
+ return E_NOTIMPL;
+ }
+
+ inline STDMETHODIMP CAXWindow::OnFocus(BOOL fGotFocus)
+ {
+ UNREFERENCED_PARAMETER(fGotFocus);
+ return E_NOTIMPL;
+ }
+
+ inline STDMETHODIMP CAXWindow::OnInPlaceActivate()
+ {
+ return S_OK;
+ }
+
+ inline STDMETHODIMP CAXWindow::OnInPlaceDeactivate()
+ {
+ return S_OK;
+ }
+
+ inline STDMETHODIMP CAXWindow::OnPosRectChange(LPCRECT lprcPosRect)
+ {
+ UNREFERENCED_PARAMETER(lprcPosRect);
+ return S_OK;
+ }
+
+ inline STDMETHODIMP CAXWindow::OnShowWindow(BOOL fShow)
+ {
+ UNREFERENCED_PARAMETER(fShow);
+ return S_OK;
+ }
+
+ inline STDMETHODIMP CAXWindow::OnUIActivate()
+ {
+ return S_OK;
+ }
+
+ inline STDMETHODIMP CAXWindow::OnUIDeactivate(BOOL fUndoable)
+ {
+ UNREFERENCED_PARAMETER(fUndoable);
+ return E_NOTIMPL;
+ }
+
+ inline STDMETHODIMP CAXWindow::QueryInterface(REFIID riid, void** ppvObject)
+ {
+ if (!ppvObject)
+ return E_POINTER;
+
+ if (IsEqualIID(riid, IID_IOleClientSite))
+ *ppvObject = (IOleClientSite*)this;
+ else if (IsEqualIID(riid, IID_IOleInPlaceSite))
+ *ppvObject = (IOleInPlaceSite*)this;
+ else if (IsEqualIID(riid, IID_IOleInPlaceFrame))
+ *ppvObject = (IOleInPlaceFrame*)this;
+ else if (IsEqualIID(riid, IID_IOleInPlaceUIWindow))
+ *ppvObject = (IOleInPlaceUIWindow*)this;
+ else if (IsEqualIID(riid, IID_IOleControlSite))
+ *ppvObject = (IOleControlSite*)this;
+ else if (IsEqualIID(riid, IID_IOleWindow))
+ *ppvObject = this;
+ else if (IsEqualIID(riid, IID_IDispatch))
+ *ppvObject = (IDispatch*)this;
+ else if (IsEqualIID(riid, IID_IUnknown))
+ *ppvObject = this;
+ else
+ {
+ *ppvObject = NULL;
+ return E_NOINTERFACE;
+ }
+
+ AddRef();
+ return S_OK;
+ }
+
+ inline STDMETHODIMP_(ULONG) CAXWindow::Release()
+ {
+ return --m_cRefs;
+ }
+
+ inline void CAXWindow::Remove()
+ {
+ if (!m_pUnk)
+ return;
+
+ IOleObject* pioo;
+ HRESULT hr = m_pUnk->QueryInterface(IID_IOleObject, (void**)&pioo);
+ if (SUCCEEDED(hr))
+ {
+ pioo->Close(OLECLOSE_NOSAVE);
+ pioo->SetClientSite(NULL);
+ pioo->Release();
+ }
+
+ IOleInPlaceObject* pipo;
+ hr = m_pUnk->QueryInterface(IID_IOleInPlaceObject, (void**)&pipo);
+ if (SUCCEEDED(hr))
+ {
+ pipo->UIDeactivate();
+ pipo->InPlaceDeactivate();
+ pipo->Release();
+ }
+
+ m_pUnk->Release();
+ m_pUnk = NULL;
+ }
+
+ inline STDMETHODIMP CAXWindow::RemoveMenus(HMENU hmenuShared)
+ {
+ UNREFERENCED_PARAMETER(hmenuShared);
+ return E_NOTIMPL;
+ }
+
+ inline STDMETHODIMP CAXWindow::RequestBorderSpace(LPCBORDERWIDTHS lpborderwidths)
+ {
+ UNREFERENCED_PARAMETER(lpborderwidths);
+ return E_NOTIMPL;
+ }
+
+ inline STDMETHODIMP CAXWindow::RequestNewObjectLayout()
+ {
+ return E_NOTIMPL;
+ }
+
+ inline STDMETHODIMP CAXWindow::SaveObject()
+ {
+ return E_NOTIMPL;
+ }
+
+ inline STDMETHODIMP CAXWindow::Scroll(SIZE scrollExtent)
+ {
+ UNREFERENCED_PARAMETER(scrollExtent);
+ return E_NOTIMPL;
+ }
+
+ inline STDMETHODIMP CAXWindow::SetActiveObject(IOleInPlaceActiveObject* pActiveObject, LPCOLESTR lpszObjName)
+ {
+ UNREFERENCED_PARAMETER(pActiveObject);
+ UNREFERENCED_PARAMETER(lpszObjName);
+ return E_NOTIMPL;
+ }
+
+ inline STDMETHODIMP CAXWindow::SetBorderSpace(LPCBORDERWIDTHS lpborderwidths)
+ {
+ UNREFERENCED_PARAMETER(lpborderwidths);
+ return E_NOTIMPL;
+ }
+
+ inline void CAXWindow::SetLocation(int x, int y, int width, int height)
+ {
+ m_rcControl.SetRect(x, y, x + width, y + height);
+
+ if (!m_pUnk)
+ return;
+
+ IOleInPlaceObject* pipo;
+ HRESULT hr = m_pUnk->QueryInterface(IID_IOleInPlaceObject, (void**)&pipo);
+ if (FAILED(hr))
+ return;
+
+ pipo->SetObjectRects(&m_rcControl, &m_rcControl);
+ pipo->Release();
+ }
+
+ inline STDMETHODIMP CAXWindow::SetMenu(HMENU hmenuShared, HOLEMENU holemenu, HWND hwndActiveObject)
+ {
+ UNREFERENCED_PARAMETER(hmenuShared);
+ UNREFERENCED_PARAMETER(holemenu);
+ UNREFERENCED_PARAMETER(hwndActiveObject);
+ return E_NOTIMPL;
+ }
+
+ inline void CAXWindow::SetParent(HWND hWndParent)
+ {
+ m_hWnd = hWndParent;
+ }
+
+ inline STDMETHODIMP CAXWindow::SetStatusText(LPCOLESTR pszStatusText)
+ {
+ if (NULL == pszStatusText)
+ return E_POINTER;
+
+ #ifndef _UNICODE
+ char status[MAX_PATH];
+ // Convert the Wide string to char
+ WideCharToMultiByte(CP_ACP, 0, pszStatusText, -1, status, MAX_PATH, NULL, NULL);
+
+ if (IsWindow(m_hWndStatus))
+ SendMessage(m_hWndStatus, SB_SETTEXT, (WPARAM)0, (LPARAM)status);
+ #else
+ if (IsWindow(m_hWndStatus))
+ SendMessage(m_hWndStatus, SB_SETTEXT, (WPARAM)0, (LPARAM)pszStatusText);
+ #endif
+
+ return (S_OK);
+ }
+
+ inline void CAXWindow::SetStatusWindow(HWND hWndStatus)
+ {
+ m_hWndStatus = hWndStatus;
+ }
+
+ inline void CAXWindow::SetVisible(BOOL fVisible)
+ {
+ if (!m_pUnk)
+ return;
+
+ IOleObject* pioo;
+ HRESULT hr = m_pUnk->QueryInterface(IID_IOleObject, (void**)&pioo);
+ if (FAILED(hr))
+ return;
+
+ if (fVisible)
+ {
+ pioo->DoVerb(OLEIVERB_INPLACEACTIVATE, NULL, this, 0, m_hWnd, &m_rcControl);
+ pioo->DoVerb(OLEIVERB_SHOW, NULL, this, 0, m_hWnd, &m_rcControl);
+ }
+ else
+ pioo->DoVerb(OLEIVERB_HIDE, NULL, this, 0, m_hWnd, NULL);
+
+ pioo->Release();
+ }
+
+ inline STDMETHODIMP CAXWindow::ShowObject()
+ {
+ return S_OK;
+ }
+
+ inline STDMETHODIMP CAXWindow::ShowPropertyFrame()
+ {
+ return E_NOTIMPL;
+ }
+
+ inline STDMETHODIMP CAXWindow::TransformCoords(POINTL* pptlHimetric, POINTF* pptfContainer, DWORD dwFlags)
+ {
+ UNREFERENCED_PARAMETER(pptlHimetric);
+ UNREFERENCED_PARAMETER(pptfContainer);
+ UNREFERENCED_PARAMETER(dwFlags);
+ return E_NOTIMPL;
+ }
+
+ inline STDMETHODIMP CAXWindow::TranslateAccelerator(LPMSG lpmsg, WORD wID)
+ {
+ UNREFERENCED_PARAMETER(lpmsg);
+ UNREFERENCED_PARAMETER(wID);
+ return S_OK;
+ }
+
+ inline STDMETHODIMP CAXWindow::TranslateAccelerator(LPMSG pMsg, DWORD grfModifiers)
+ {
+ UNREFERENCED_PARAMETER(pMsg);
+ UNREFERENCED_PARAMETER(grfModifiers);
+ return S_FALSE;
+ }
+
+ inline void CAXWindow::TranslateKey(MSG msg)
+ {
+ if (!m_pUnk)
+ return;
+
+ IOleInPlaceActiveObject* pao;
+ HRESULT hr = m_pUnk->QueryInterface(IID_IOleInPlaceActiveObject, (void**)&pao);
+ if (FAILED(hr))
+ return;
+
+ pao->TranslateAccelerator(&msg);
+ pao->Release();
+ }
+
+
+ ////////////////////////////////////////
+ // Definitions for the CWebBrowser class
+ //
+ inline CWebBrowser::CWebBrowser() : m_pIWebBrowser2(0)
+ {
+ OleInitialize(NULL);
+ }
+
+ inline CWebBrowser::~CWebBrowser()
+ {
+ if (m_pIWebBrowser2)
+ {
+ m_pIWebBrowser2->Stop();
+ m_pIWebBrowser2->Release();
+ }
+
+ OleUninitialize();
+ }
+
+ inline void CWebBrowser::AddWebBrowserControl()
+ {
+ GetAXWindow().CreateControl(CLSID_WebBrowser);
+ GetAXWindow().SetParent(m_hWnd);
+ GetAXWindow().SetVisible(TRUE);
+ GetAXWindow().Activate(TRUE);
+
+ IUnknown* pUnk = GetAXWindow().GetUnknown();
+ if(pUnk)
+ {
+ // Store the pointer to the WebBrowser control
+ HRESULT hr = pUnk->QueryInterface(IID_IWebBrowser2, (void**)&m_pIWebBrowser2);
+ pUnk->Release();
+
+ // Navigate to an empty page
+ if (SUCCEEDED(hr))
+ {
+ VARIANT vURL;
+ vURL.vt = VT_BSTR;
+ vURL.bstrVal = SysAllocString(L"about:blank");
+ VARIANT ve1, ve2, ve3, ve4;
+ ve1.vt = VT_EMPTY;
+ ve2.vt = VT_EMPTY;
+ ve3.vt = VT_EMPTY;
+ ve4.vt = VT_EMPTY;
+
+ m_pIWebBrowser2->Navigate2(&vURL, &ve1, &ve2, &ve3, &ve4);
+
+ VariantClear(&vURL);
+ }
+ }
+ }
+
+ inline void CWebBrowser::Navigate(LPCTSTR pTChar)
+ {
+ // Navigate to our web page
+ VARIANT vURL;
+ vURL.vt = VT_BSTR;
+ vURL.bstrVal = SysAllocString(T2W(pTChar));
+ VARIANT ve1, ve2, ve3, ve4;
+ ve1.vt = VT_EMPTY;
+ ve2.vt = VT_EMPTY;
+ ve3.vt = VT_EMPTY;
+ ve4.vt = VT_EMPTY;
+
+ GetIWebBrowser2()->Navigate2(&vURL, &ve1, &ve2, &ve3, &ve4);
+
+ VariantClear(&vURL); // Also frees memory allocated by SysAllocateString
+ }
+
+ inline void CWebBrowser::OnCreate()
+ {
+ AddWebBrowserControl();
+ }
+
+ inline void CWebBrowser::OnSize(int width, int height)
+ {
+ // position the container
+ GetAXWindow().SetLocation(0, 0, width, height);
+ }
+
+ inline LRESULT CWebBrowser::WndProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam)
+ {
+ switch(uMsg)
+ {
+ case WM_SIZE:
+ OnSize(LOWORD(lParam), HIWORD(lParam));
+ break;
+ case WM_DESTROY:
+ GetAXWindow().Remove();
+ break;
+ }
+
+ return CWnd::WndProcDefault(uMsg, wParam, lParam);
+ }
+
+}
+
+#endif // _WIN32XX_WEBBROWSER_H_
+
diff --git a/mmc_updater/depends/win32cpp/wincore.h b/mmc_updater/depends/win32cpp/wincore.h
new file mode 100644
index 00000000..d6b1f9b6
--- /dev/null
+++ b/mmc_updater/depends/win32cpp/wincore.h
@@ -0,0 +1,2977 @@
+// Win32++ Version 7.2
+// Released: 5th AUgust 2011
+//
+// David Nash
+// email: dnash@bigpond.net.au
+// url: https://sourceforge.net/projects/win32-framework
+//
+//
+// Copyright (c) 2005-2011 David Nash
+//
+// Permission is hereby granted, free of charge, to
+// any person obtaining a copy of this software and
+// associated documentation files (the "Software"),
+// to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify,
+// merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom
+// the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice
+// shall be included in all copies or substantial portions
+// of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
+// OR OTHER DEALINGS IN THE SOFTWARE.
+//
+////////////////////////////////////////////////////////
+
+
+///////////////////////////////////////////////////////
+// wincore.h
+// Declaration of the following classes:
+// CWinApp, CWnd, CWinException, CCriticalSection,
+// CPoint, CRect, and CSize
+//
+// This file contains the declarations for the core set of classes required to
+// create simple windows using Win32++.
+//
+// 1) CCriticalSection: This class is used internally to manage thread access
+// to shared resources. You can also use this class to lock and
+// release your own critical sections.
+//
+// 2) CWinException: This class is used internally by Win32++ to handle
+// exceptions. You can also use it to throw and catch exceptions.
+//
+// 3) WinApp: This class is used start Win32++ and run the message loop. You
+// should inherit from this class to start Win32++ in your own
+// application.
+//
+// 4) CWnd: This class is used to represent a window. It provides a means
+// of creating the window, and handling its messages. Inherit
+// from this class to define and control windows.
+//
+//
+// Note: This header file (or another Win32++ header file which includes it)
+// should be included before all other header files. It sets some
+// important macros which need to be set before including Windows.h
+// Including this file first also allows it to disable some pointless
+// warning messages (see below).
+
+
+
+#ifndef _WIN32XX_WINCORE_H_
+#define _WIN32XX_WINCORE_H_
+
+
+// Remove pointless warning messages
+#ifdef _MSC_VER
+ #pragma warning (disable : 4996) // function or variable may be unsafe (deprecated)
+ #ifndef _CRT_SECURE_NO_WARNINGS
+ #define _CRT_SECURE_NO_WARNINGS // eliminate deprecation warnings for VS2005/VS2010
+ #endif
+ #if _MSC_VER < 1500
+ #pragma warning (disable : 4511) // copy operator could not be generated
+ #pragma warning (disable : 4512) // assignment operator could not be generated
+ #pragma warning (disable : 4702) // unreachable code (bugs in Microsoft's STL)
+ #pragma warning (disable : 4786) // identifier was truncated
+ #endif
+#endif
+
+#ifdef __BORLANDC__
+ #pragma option -w-8019 // code has no effect
+ #pragma option -w-8026 // functions with exception specifiations are not expanded inline
+ #pragma option -w-8027 // function not expanded inline
+ #define STRICT 1
+#endif
+
+#ifdef __GNUC__
+ #pragma GCC diagnostic ignored "-Wmissing-braces"
+ #pragma GCC diagnostic ignored "-Wunused-value"
+#endif
+
+#ifdef _WIN32_WCE
+ #include "wcestddef.h"
+#endif
+
+#define _WINSOCKAPI_ // Prevent winsock.h #include's.
+
+#include <assert.h>
+#include <vector>
+#include <algorithm>
+#include <string>
+#include <map>
+#include <windows.h>
+#include <commctrl.h>
+#include <stdio.h>
+#include <tchar.h>
+#include <shlwapi.h>
+#include "shared_ptr.h"
+//#include "winutils.h" // included later in this file
+//#include "cstring.h" // included later in this file
+//#include "gdi.h" // included later in this file
+//#include "menu.h" // included later in this file
+
+// For compilers lacking Win64 support
+#ifndef GetWindowLongPtr
+ #define GetWindowLongPtr GetWindowLong
+ #define SetWindowLongPtr SetWindowLong
+ #define GWLP_WNDPROC GWL_WNDPROC
+ #define GWLP_HINSTANCE GWL_HINSTANCE
+ #define GWLP_ID GWL_ID
+ #define GWLP_USERDATA GWL_USERDATA
+ #define DWLP_DLGPROC DWL_DLGPROC
+ #define DWLP_MSGRESULT DWL_MSGRESULT
+ #define DWLP_USER DWL_USER
+ #define DWORD_PTR DWORD
+ #define LONG_PTR LONG
+ #define ULONG_PTR LONG
+#endif
+#ifndef GetClassLongPtr
+ #define GetClassLongPtr GetClassLong
+ #define SetClassLongPtr SetClassLong
+ #define GCLP_HBRBACKGROUND GCL_HBRBACKGROUND
+ #define GCLP_HCURSOR GCL_HCURSOR
+ #define GCLP_HICON GCL_HICON
+ #define GCLP_HICONSM GCL_HICONSM
+ #define GCLP_HMODULE GCL_HMODULE
+ #define GCLP_MENUNAME GCL_MENUNAME
+ #define GCLP_WNDPROC GCL_WNDPROC
+#endif
+
+
+// Messages defined by Win32++
+#define UWM_POPUPMENU (WM_APP + 1) // Message - creates the menubar popup menu
+#define UWM_DOCK_START (WM_APP + 2) // Notification - about to start undocking
+#define UWM_DOCK_MOVE (WM_APP + 3) // Notification - undocked docker is being moved
+#define UWM_DOCK_END (WM_APP + 4) // Notification - docker has been docked
+#define UWM_BAR_START (WM_APP + 5) // Notification - docker bar selected for move
+#define UWM_BAR_MOVE (WM_APP + 6) // Notification - docker bar moved
+#define UWM_BAR_END (WM_APP + 7) // Notification - end of docker bar move
+#define UWM_UNDOCKED (WM_APP + 8) // Notification - sent by docker when undocked
+#define UWM_FRAMELOSTFOCUS (WM_APP + 9) // Notification - sent by frame to view window when focus lost
+#define UWM_FRAMEGOTFOCUS (WM_APP + 10) // Notification - sent by frame to view window when focus acquired
+#define UWM_DOCK_DESTROYED (WM_APP + 11) // Message - posted when docker is destroyed
+#define UWM_TAB_CHANGED (WM_APP + 12) // Notification - tab layout changed
+#define UWM_TOOLBAR_RESIZE (WM_APP + 13) // Message - sent by toolbar to parent. Used by the rebar
+#define UWM_UPDATE_COMMAND (WM_APP + 14) // Message - sent before a menu is displayed. Used by OnUpdate
+#define UWM_DOCK_ACTIVATED (WM_APP + 15) // Message - sent to dock ancestor when a docker is activated or deactivated.
+#define UWM_GETMENUTHEME (WM_APP + 16) // Message - returns a pointer to MenuTheme
+#define UWM_GETREBARTHEME (WM_APP + 17) // Message - returns a pointer to CToolBar
+#define UWM_GETTOOLBARTHEME (WM_APP + 18) // Message - returns a pointer to ToolBarTheme
+#define UWM_CLEANUPTEMPS (WM_APP + 19) // Message - posted to cleanup temporary CDCs
+
+
+// Automatically include the Win32xx namespace
+// define NO_USING_NAMESPACE to skip this step
+namespace Win32xx {}
+#ifndef NO_USING_NAMESPACE
+ using namespace Win32xx;
+#endif
+
+// Required for WinCE
+#ifndef TLS_OUT_OF_INDEXES
+ #define TLS_OUT_OF_INDEXES ((DWORD_PTR) -1)
+#endif
+#ifndef WM_PARENTNOTIFY
+ #define WM_PARENTNOTIFY 0x0210
+#endif
+
+
+namespace Win32xx
+{
+
+ ////////////////////////////////////////////////
+ // Forward declarations.
+ // These classes are defined later or elsewhere
+ class CDC;
+ class CGDIObject;
+ class CMenu;
+ class CWinApp;
+ class CWnd;
+ class CBitmap;
+ class CBrush;
+ class CFont;
+ class CPalette;
+ class CPen;
+ class CRgn;
+
+ // tString is a TCHAR std::string
+ typedef std::basic_string<TCHAR> tString;
+
+ // tStringStream is a TCHAR std::stringstream
+ typedef std::basic_stringstream<TCHAR> tStringStream;
+
+ // Some useful smart pointers
+ typedef Shared_Ptr<CDC> DCPtr;
+ typedef Shared_Ptr<CGDIObject> GDIPtr;
+ typedef Shared_Ptr<CMenu> MenuPtr;
+ typedef Shared_Ptr<CWnd> WndPtr;
+ typedef Shared_Ptr<CBitmap> BitmapPtr;
+ typedef Shared_Ptr<CBrush> BrushPtr;
+ typedef Shared_Ptr<CFont> FontPtr;
+ typedef Shared_Ptr<CPalette> PalettePtr;
+ typedef Shared_Ptr<CPen> PenPtr;
+ typedef Shared_Ptr<CRgn> RgnPtr;
+
+ enum Constants // Defines the maximum size for TCHAR strings
+ {
+ MAX_MENU_STRING = 80,
+ MAX_STRING_SIZE = 255,
+ };
+
+ struct CompareHDC // The comparison function object used by CWinApp::m_mapHDC
+ {
+ bool operator()(HDC const a, const HDC b) const
+ {return ((DWORD_PTR)a < (DWORD_PTR)b);}
+ };
+
+ struct CompareGDI // The comparison function object used by CWinApp::m_mapGDI
+ {
+ bool operator()(HGDIOBJ const a, const HGDIOBJ b) const
+ {return ((DWORD_PTR)a < (DWORD_PTR)b);}
+ };
+
+ struct CompareHMENU // The comparison function object used by CWinApp::m_mapHMENU
+ {
+ bool operator()(HMENU const a, const HMENU b) const
+ {return ((DWORD_PTR)a < (DWORD_PTR)b);}
+ };
+
+ struct CompareHWND // The comparison function object used by CWinApp::m_mapHWND
+ {
+ bool operator()(HWND const a, const HWND b) const
+ {return ((DWORD_PTR)a < (DWORD_PTR)b);}
+ };
+
+ struct TLSData // Used for Thread Local Storage (TLS)
+ {
+ CWnd* pCWnd; // pointer to CWnd object for Window creation
+ CWnd* pMenuBar; // pointer to CMenuBar object used for the WH_MSGFILTER hook
+ HHOOK hHook; // WH_MSGFILTER hook for CMenuBar and Modeless Dialogs
+
+ std::vector<DCPtr> vTmpDCs; // A vector of temporary CDC pointers
+ std::vector<GDIPtr> vTmpGDIs; // A vector of temporary CGDIObject pointers
+ std::vector<WndPtr> vTmpWnds; // A vector of temporary CWnd pointers
+ TLSData() : pCWnd(0), pMenuBar(0), hHook(0) {}
+
+#ifndef _WIN32_WCE
+ std::vector<MenuPtr> vTmpMenus; // A vector of temporary CMenu pointers
+#endif
+ };
+
+
+ /////////////////////////////////////////
+ // Declarations for the CCriticalSection class
+ // This class is used for thread synchronisation
+ class CCriticalSection
+ {
+ public:
+ CCriticalSection() { ::InitializeCriticalSection(&m_cs); }
+ ~CCriticalSection() { ::DeleteCriticalSection(&m_cs); }
+
+ void Lock() { ::EnterCriticalSection(&m_cs); }
+ void Release() { ::LeaveCriticalSection(&m_cs); }
+
+ private:
+ CCriticalSection ( const CCriticalSection& );
+ CCriticalSection& operator = ( const CCriticalSection& );
+
+ CRITICAL_SECTION m_cs;
+ };
+
+
+ ////////////////////////////////////////
+ // Declaration of the CWinException class
+ //
+ // Note: Each function guarantees not to throw an exception
+
+ class CWinException : public std::exception
+ {
+ public:
+ CWinException(LPCTSTR pszText) throw ();
+ ~CWinException() throw() {}
+ DWORD GetError() const throw ();
+ LPCTSTR GetErrorString() const throw ();
+ const char * what () const throw ();
+
+ private:
+ DWORD m_Error;
+ LPCTSTR m_pszText;
+ TCHAR m_szErrorString[MAX_STRING_SIZE];
+ };
+
+
+ ///////////////////////////////////
+ // Declaration of the CWinApp class
+ //
+ class CWinApp
+ {
+ // Provide these access to CWinApp's private members:
+ friend class CDC;
+ friend class CDialog;
+ friend class CGDIObject;
+ friend class CMenu;
+ friend class CMenuBar;
+ friend class CPropertyPage;
+ friend class CPropertySheet;
+ friend class CTaskDialog;
+ friend class CWnd;
+ friend CWinApp* GetApp();
+ friend CGDIObject* FromHandle(HGDIOBJ hObject);
+ friend CBitmap* FromHandle(HBITMAP hBitmap);
+ friend CBrush* FromHandle(HBRUSH hBrush);
+ friend CFont* FromHandle(HFONT hFont);
+ friend CPalette* FromHandle(HPALETTE hPalette);
+ friend CPen* FromHandle(HPEN hPen);
+ friend CRgn* FromHandle(HRGN hRgn);
+ friend CDC* FromHandle(HDC hDC);
+ friend CWnd* FromHandle(HWND hWnd);
+#ifndef _WIN32_WCE
+ friend CMenu* FromHandle(HMENU hMenu);
+#endif
+
+ typedef Shared_Ptr<TLSData> TLSDataPtr;
+
+ public:
+ CWinApp();
+ virtual ~CWinApp();
+
+ HACCEL GetAccelerators() const { return m_hAccel; }
+ HINSTANCE GetInstanceHandle() const { return m_hInstance; }
+ HINSTANCE GetResourceHandle() const { return (m_hResource ? m_hResource : m_hInstance); }
+ void SetAccelerators(HACCEL hAccel, CWnd* pWndAccel);
+ void SetResourceHandle(HINSTANCE hResource);
+
+ // These are the functions you might wish to override
+ virtual BOOL InitInstance();
+ virtual int MessageLoop();
+ virtual int Run();
+
+ protected:
+ virtual BOOL OnIdle(LONG lCount);
+ virtual BOOL PreTranslateMessage(MSG Msg);
+
+ private:
+ CWinApp(const CWinApp&); // Disable copy construction
+ CWinApp& operator = (const CWinApp&); // Disable assignment operator
+ CDC* GetCDCFromMap(HDC hDC);
+ CGDIObject* GetCGDIObjectFromMap(HGDIOBJ hObject);
+ CMenu* GetCMenuFromMap(HMENU hMenu);
+ CWnd* GetCWndFromMap(HWND hWnd);
+
+ void AddTmpDC(CDC* pDC);
+ void AddTmpGDI(CGDIObject* pObject);
+ CMenu* AddTmpMenu(HMENU hMenu);
+ CWnd* AddTmpWnd(HWND hWnd);
+ void CleanupTemps();
+ DWORD GetTlsIndex() const {return m_dwTlsIndex;}
+ void SetCallback();
+ TLSData* SetTlsIndex();
+ static CWinApp* SetnGetThis(CWinApp* pThis = 0);
+
+ std::map<HDC, CDC*, CompareHDC> m_mapHDC; // maps device context handles to CDC objects
+ std::map<HGDIOBJ, CGDIObject*, CompareGDI> m_mapGDI; // maps GDI handles to CGDIObjects.
+ std::map<HMENU, CMenu*, CompareHMENU> m_mapHMENU; // maps menu handles to CMenu objects
+ std::map<HWND, CWnd*, CompareHWND> m_mapHWND; // maps window handles to CWnd objects
+ std::vector<TLSDataPtr> m_vTLSData; // vector of TLSData smart pointers, one for each thread
+ CCriticalSection m_csMapLock; // thread synchronisation for m_mapHWND
+ CCriticalSection m_csTLSLock; // thread synchronisation for m_vTLSData
+ CCriticalSection m_csAppStart; // thread synchronisation for application startup
+ HINSTANCE m_hInstance; // handle to the applications instance
+ HINSTANCE m_hResource; // handle to the applications resources
+ DWORD m_dwTlsIndex; // Thread Local Storage index
+ WNDPROC m_Callback; // callback address of CWnd::StaticWndowProc
+ HACCEL m_hAccel; // handle to the accelerator table
+ CWnd* m_pWndAccel; // handle to the window for accelerator keys
+
+ };
+
+}
+
+#include "winutils.h"
+#include "cstring.h"
+
+
+namespace Win32xx
+{
+ ////////////////////////////////
+ // Declaration of the CWnd class
+ //
+ class CWnd
+ {
+ friend class CMDIChild;
+ friend class CDialog;
+ friend class CPropertyPage;
+ friend class CTaskDialog;
+ friend class CWinApp;
+
+ public:
+ CWnd(); // Constructor
+ virtual ~CWnd(); // Destructor
+
+ // These virtual functions can be overridden
+ virtual BOOL Attach(HWND hWnd);
+ virtual BOOL AttachDlgItem(UINT nID, CWnd* pParent);
+ virtual void CenterWindow() const;
+ virtual HWND Create(CWnd* pParent = NULL);
+ virtual HWND CreateEx(DWORD dwExStyle, LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, int x, int y, int nWidth, int nHeight, CWnd* pParent, CMenu* pMenu, LPVOID lpParam = NULL);
+ virtual HWND CreateEx(DWORD dwExStyle, LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rc, CWnd* pParent, CMenu* pMenu, LPVOID lpParam = NULL);
+ virtual void Destroy();
+ virtual HWND Detach();
+ virtual HICON SetIconLarge(int nIcon);
+ virtual HICON SetIconSmall(int nIcon);
+
+ // Attributes
+ HWND GetHwnd() const { return m_hWnd; }
+ WNDPROC GetPrevWindowProc() const { return m_PrevWindowProc; }
+
+ // Wrappers for Win32 API functions
+ // These functions aren't virtual, and shouldn't be overridden
+ CDC* BeginPaint(PAINTSTRUCT& ps) const;
+ BOOL BringWindowToTop() const;
+ LRESULT CallWindowProc(WNDPROC lpPrevWndFunc, UINT Msg, WPARAM wParam, LPARAM lParam) const;
+ BOOL CheckDlgButton(int nIDButton, UINT uCheck) const;
+ BOOL CheckRadioButton(int nIDFirstButton, int nIDLastButton, int nIDCheckButton) const;
+ CWnd* ChildWindowFromPoint(POINT pt) const;
+ BOOL ClientToScreen(POINT& pt) const;
+ BOOL ClientToScreen(RECT& rc) const;
+ LRESULT DefWindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam) const;
+ HDWP DeferWindowPos(HDWP hWinPosInfo, HWND hWndInsertAfter, int x, int y, int cx, int cy, UINT uFlags) const;
+ HDWP DeferWindowPos(HDWP hWinPosInfo, HWND hWndInsertAfter, const RECT& rc, UINT uFlags) const;
+ BOOL DrawMenuBar() const;
+ BOOL EnableWindow(BOOL bEnable = TRUE) const;
+ BOOL EndPaint(PAINTSTRUCT& ps) const;
+ CWnd* GetActiveWindow() const;
+ CWnd* GetAncestor(UINT gaFlag = 3 /*= GA_ROOTOWNER*/) const;
+ CWnd* GetCapture() const;
+ ULONG_PTR GetClassLongPtr(int nIndex) const;
+ CString GetClassName() const;
+ CRect GetClientRect() const;
+ CDC* GetDC() const;
+ CDC* GetDCEx(HRGN hrgnClip, DWORD flags) const;
+ CWnd* GetDesktopWindow() const;
+ CWnd* GetDlgItem(int nIDDlgItem) const;
+ UINT GetDlgItemInt(int nIDDlgItem, BOOL* lpTranslated, BOOL bSigned) const;
+ CString GetDlgItemText(int nIDDlgItem) const;
+ CWnd* GetFocus() const;
+ CFont* GetFont() const;
+ HICON GetIcon(BOOL bBigIcon) const;
+ CWnd* GetNextDlgGroupItem(CWnd* pCtl, BOOL bPrevious) const;
+ CWnd* GetNextDlgTabItem(CWnd* pCtl, BOOL bPrevious) const;
+ CWnd* GetParent() const;
+ BOOL GetScrollInfo(int fnBar, SCROLLINFO& si) const;
+ CRect GetUpdateRect(BOOL bErase) const;
+ int GetUpdateRgn(CRgn* pRgn, BOOL bErase) const;
+ CWnd* GetWindow(UINT uCmd) const;
+ CDC* GetWindowDC() const;
+ LONG_PTR GetWindowLongPtr(int nIndex) const;
+ CRect GetWindowRect() const;
+ CString GetWindowText() const;
+ int GetWindowTextLength() const;
+ void Invalidate(BOOL bErase = TRUE) const;
+ BOOL InvalidateRect(LPCRECT lpRect, BOOL bErase = TRUE) const;
+ BOOL InvalidateRgn(CRgn* pRgn, BOOL bErase = TRUE) const;
+ BOOL IsChild(CWnd* pChild) const;
+ BOOL IsDialogMessage(LPMSG lpMsg) const;
+ UINT IsDlgButtonChecked(int nIDButton) const;
+ BOOL IsWindow() const;
+ BOOL IsWindowEnabled() const;
+ BOOL IsWindowVisible() const;
+ BOOL KillTimer(UINT_PTR uIDEvent) const;
+ int MessageBox(LPCTSTR lpText, LPCTSTR lpCaption, UINT uType) const;
+ void MapWindowPoints(CWnd* pWndTo, POINT& pt) const;
+ void MapWindowPoints(CWnd* pWndTo, RECT& rc) const;
+ void MapWindowPoints(CWnd* pWndTo, LPPOINT ptArray, UINT nCount) const;
+ BOOL MoveWindow(int x, int y, int nWidth, int nHeight, BOOL bRepaint = TRUE) const;
+ BOOL MoveWindow(const RECT& rc, BOOL bRepaint = TRUE) const;
+ BOOL PostMessage(UINT uMsg, WPARAM wParam = 0L, LPARAM lParam = 0L) const;
+ BOOL PostMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) const;
+ BOOL RedrawWindow(LPCRECT lpRectUpdate = NULL, CRgn* pRgn = NULL, UINT flags = RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE | RDW_ALLCHILDREN) const;
+ int ReleaseDC(CDC* pDC) const;
+ BOOL ScreenToClient(POINT& Point) const;
+ BOOL ScreenToClient(RECT& rc) const;
+ LRESULT SendDlgItemMessage(int nIDDlgItem, UINT Msg, WPARAM wParam, LPARAM lParam) const;
+ LRESULT SendMessage(UINT uMsg, WPARAM wParam = 0L, LPARAM lParam = 0L) const;
+ LRESULT SendMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) const;
+ BOOL SendNotifyMessage(UINT Msg, WPARAM wParam, LPARAM lParam) const;
+ CWnd* SetActiveWindow() const;
+ CWnd* SetCapture() const;
+ ULONG_PTR SetClassLongPtr(int nIndex, LONG_PTR dwNewLong) const;
+ BOOL SetDlgItemInt(int nIDDlgItem, UINT uValue, BOOL bSigned) const;
+ BOOL SetDlgItemText(int nIDDlgItem, LPCTSTR lpString) const;
+ CWnd* SetFocus() const;
+ void SetFont(CFont* pFont, BOOL bRedraw = TRUE) const;
+ BOOL SetForegroundWindow() const;
+ HICON SetIcon(HICON hIcon, BOOL bBigIcon) const;
+ CWnd* SetParent(CWnd* pWndParent) const;
+ BOOL SetRedraw(BOOL bRedraw = TRUE) const;
+ int SetScrollInfo(int fnBar, const SCROLLINFO& si, BOOL fRedraw) const;
+ UINT_PTR SetTimer(UINT_PTR nIDEvent, UINT uElapse, TIMERPROC lpTimerFunc) const;
+ LONG_PTR SetWindowLongPtr(int nIndex, LONG_PTR dwNewLong) const;
+ BOOL SetWindowPos(HWND hWndInsertAfter, int x, int y, int cx, int cy, UINT uFlags) const;
+ BOOL SetWindowPos(HWND hWndInsertAfter, const RECT& rc, UINT uFlags) const;
+ int SetWindowRgn(CRgn* pRgn, BOOL bRedraw = TRUE) const;
+ BOOL SetWindowText(LPCTSTR lpString) const;
+ HRESULT SetWindowTheme(LPCWSTR pszSubAppName, LPCWSTR pszSubIdList) const;
+ BOOL ShowWindow(int nCmdShow = SW_SHOWNORMAL) const;
+ BOOL UpdateWindow() const;
+ BOOL ValidateRect(LPCRECT prc) const;
+ BOOL ValidateRgn(CRgn* pRgn) const;
+ static CWnd* WindowFromPoint(POINT pt);
+
+ #ifndef _WIN32_WCE
+ BOOL CloseWindow() const;
+ int DlgDirList(LPTSTR lpPathSpec, int nIDListBox, int nIDStaticPath, UINT uFileType) const;
+ int DlgDirListComboBox(LPTSTR lpPathSpec, int nIDComboBox, int nIDStaticPath, UINT uFiletype) const;
+ BOOL DlgDirSelectEx(LPTSTR lpString, int nCount, int nIDListBox) const;
+ BOOL DlgDirSelectComboBoxEx(LPTSTR lpString, int nCount, int nIDComboBox) const;
+ BOOL DrawAnimatedRects(int idAni, RECT& rcFrom, RECT& rcTo) const;
+ BOOL DrawCaption(CDC* pDC, RECT& rc, UINT uFlags) const;
+ BOOL EnableScrollBar(UINT uSBflags, UINT uArrows) const;
+ CWnd* GetLastActivePopup() const;
+ CMenu* GetMenu() const;
+ int GetScrollPos(int nBar) const;
+ BOOL GetScrollRange(int nBar, int& MinPos, int& MaxPos) const;
+ CMenu* GetSystemMenu(BOOL bRevert) const;
+ CWnd* GetTopWindow() const;
+ BOOL GetWindowPlacement(WINDOWPLACEMENT& pWndpl) const;
+ BOOL HiliteMenuItem(CMenu* pMenu, UINT uItemHilite, UINT uHilite) const;
+ BOOL IsIconic() const;
+ BOOL IsZoomed() const;
+ BOOL LockWindowUpdate() const;
+ BOOL OpenIcon() const;
+ void Print(CDC* pDC, DWORD dwFlags) const;
+ BOOL SetMenu(CMenu* pMenu) const;
+ BOOL ScrollWindow(int XAmount, int YAmount, LPCRECT lprcScroll, LPCRECT lprcClip) const;
+ int ScrollWindowEx(int dx, int dy, LPCRECT lprcScroll, LPCRECT lprcClip, CRgn* prgnUpdate, LPRECT lprcUpdate, UINT flags) const;
+ int SetScrollPos(int nBar, int nPos, BOOL bRedraw) const;
+ BOOL SetScrollRange(int nBar, int nMinPos, int nMaxPos, BOOL bRedraw) const;
+ BOOL SetWindowPlacement(const WINDOWPLACEMENT& wndpl) const;
+ BOOL ShowOwnedPopups(BOOL fShow) const;
+ BOOL ShowScrollBar(int nBar, BOOL bShow) const;
+ BOOL ShowWindowAsync(int nCmdShow) const;
+ BOOL UnLockWindowUpdate() const;
+ CWnd* WindowFromDC(CDC* pDC) const;
+
+ #ifndef WIN32_LEAN_AND_MEAN
+ void DragAcceptFiles(BOOL fAccept) const;
+ #endif
+ #endif
+
+ static LRESULT CALLBACK StaticWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
+ operator HWND() const { return m_hWnd; }
+
+ protected:
+ // Override these functions as required
+ virtual LRESULT FinalWindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam);
+ virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam);
+ virtual void OnCreate();
+ virtual void OnDraw(CDC* pDC);
+ virtual BOOL OnEraseBkgnd(CDC* pDC);
+ virtual void OnInitialUpdate();
+ virtual void OnMenuUpdate(UINT nID);
+ virtual LRESULT OnMessageReflect(UINT uMsg, WPARAM wParam, LPARAM lParam);
+ virtual LRESULT OnNotify(WPARAM wParam, LPARAM lParam);
+ virtual LRESULT OnNotifyReflect(WPARAM wParam, LPARAM lParam);
+ virtual void PreCreate(CREATESTRUCT& cs);
+ virtual void PreRegisterClass(WNDCLASS& wc);
+ virtual BOOL PreTranslateMessage(MSG* pMsg);
+ virtual LRESULT WndProc(UINT uMsg, WPARAM wParam, LPARAM lParam);
+ virtual LRESULT WndProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam);
+
+ HWND m_hWnd; // handle to this object's window
+
+ private:
+ CWnd(const CWnd&); // Disable copy construction
+ CWnd& operator = (const CWnd&); // Disable assignment operator
+ void AddToMap();
+ void Cleanup();
+ LRESULT MessageReflect(HWND hwndParent, UINT uMsg, WPARAM wParam, LPARAM lParam);
+ BOOL RegisterClass(WNDCLASS& wc);
+ BOOL RemoveFromMap();
+ void Subclass(HWND hWnd);
+
+ Shared_Ptr<WNDCLASS> m_pwc; // defines initialisation parameters for PreRegisterClass
+ Shared_Ptr<CREATESTRUCT> m_pcs; // defines initialisation parameters for PreCreate and Create
+ WNDPROC m_PrevWindowProc; // pre-subclassed Window Procedure
+ BOOL m_IsTmpWnd; // True if this CWnd is a TmpWnd
+
+ }; // class CWnd
+
+}
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+#include "gdi.h"
+#include "menu.h"
+
+namespace Win32xx
+{
+
+ //////////////////////////////////////////
+ // Definitions for the CWinException class
+ //
+ inline CWinException::CWinException(LPCTSTR pszText) throw () : m_Error(::GetLastError()), m_pszText(pszText)
+ {
+ memset(m_szErrorString, 0, MAX_STRING_SIZE * sizeof(TCHAR));
+
+ if (m_Error != 0)
+ {
+ DWORD dwFlags = FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS;
+ ::FormatMessage(dwFlags, NULL, m_Error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), m_szErrorString, MAX_STRING_SIZE-1, NULL);
+ }
+ }
+
+ inline DWORD CWinException::GetError() const throw ()
+ {
+ return m_Error;
+ }
+
+ inline LPCTSTR CWinException::GetErrorString() const throw ()
+ {
+ return m_szErrorString;
+ }
+
+ inline const char * CWinException::what() const throw ()
+ {
+ // Sends the last error string to the debugger (typically displayed in the IDE's output window).
+ ::OutputDebugString(m_szErrorString);
+ return "CWinException thrown";
+ }
+
+
+ ////////////////////////////////////
+ // Definitions for the CWinApp class
+ //
+
+ // To begin Win32++, inherit your application class from this one.
+ // You must run only one instance of the class inherited from this.
+ inline CWinApp::CWinApp() : m_Callback(NULL), m_hAccel(0), m_pWndAccel(0)
+ {
+ try
+ {
+ m_csAppStart.Lock();
+ assert( 0 == SetnGetThis() ); // Test if this is the first instance of CWinApp
+
+ m_dwTlsIndex = ::TlsAlloc();
+ if (m_dwTlsIndex == TLS_OUT_OF_INDEXES)
+ {
+ // We only get here in the unlikely event that all TLS indexes are already allocated by this app
+ // At least 64 TLS indexes per process are allowed. Win32++ requires only one TLS index.
+ m_csAppStart.Release();
+ throw CWinException(_T("CWinApp::CWinApp Failed to allocate TLS Index"));
+ }
+
+ SetnGetThis(this);
+ m_csAppStart.Release();
+
+ // Set the instance handle
+ #ifdef _WIN32_WCE
+ m_hInstance = (HINSTANCE)GetModuleHandle(0);
+ #else
+ MEMORY_BASIC_INFORMATION mbi = {0};
+ VirtualQuery( (LPCVOID)SetnGetThis, &mbi, sizeof(mbi) );
+ assert(mbi.AllocationBase);
+ m_hInstance = (HINSTANCE)mbi.AllocationBase;
+ #endif
+
+ m_hResource = m_hInstance;
+ SetCallback();
+ }
+
+ catch (const CWinException &e)
+ {
+ e.what();
+ throw;
+ }
+ }
+
+ inline CWinApp::~CWinApp()
+ {
+ std::vector<TLSDataPtr>::iterator iter;
+ for (iter = m_vTLSData.begin(); iter < m_vTLSData.end(); ++iter)
+ {
+ (*iter)->vTmpDCs.clear();
+#ifndef _WIN32_WCE
+ (*iter)->vTmpMenus.clear();
+#endif
+ (*iter)->vTmpWnds.clear();
+ }
+
+ // Check that all CWnd windows are destroyed
+ std::map<HWND, CWnd*, CompareHWND>::iterator m;
+ for (m = m_mapHWND.begin(); m != m_mapHWND.end(); ++m)
+ {
+ HWND hWnd = (*m).first;
+ if (::IsWindow(hWnd))
+ ::DestroyWindow(hWnd);
+ }
+ m_mapHWND.clear();
+ m_mapGDI.clear();
+ m_mapHDC.clear();
+ m_mapHMENU.clear();
+
+ // Do remaining tidy up
+ if (m_dwTlsIndex != TLS_OUT_OF_INDEXES)
+ {
+ ::TlsSetValue(GetTlsIndex(), NULL);
+ ::TlsFree(m_dwTlsIndex);
+ }
+
+ SetnGetThis((CWinApp*)-1);
+ }
+
+ inline void CWinApp::AddTmpDC(CDC* pDC)
+ {
+ // The TmpMenus are created by GetSybMenu.
+ // They are removed by CleanupTemps
+ assert(pDC);
+
+ // Ensure this thread has the TLS index set
+ TLSData* pTLSData = GetApp()->SetTlsIndex();
+ pTLSData->vTmpDCs.push_back(pDC); // save pDC as a smart pointer
+ }
+
+ inline void CWinApp::AddTmpGDI(CGDIObject* pObject)
+ {
+ // The temporary CGDIObjects are removed by CleanupTemps
+ assert(pObject);
+
+ // Ensure this thread has the TLS index set
+ TLSData* pTLSData = GetApp()->SetTlsIndex();
+ pTLSData->vTmpGDIs.push_back(pObject); // save pObject as a smart pointer
+ }
+
+#ifndef _WIN32_WCE
+ inline CMenu* CWinApp::AddTmpMenu(HMENU hMenu)
+ {
+ // The TmpMenus are created by GetSybMenu.
+ // They are removed by CleanupTemps
+ assert(::IsMenu(hMenu));
+ assert(!GetCMenuFromMap(hMenu));
+
+ CMenu* pMenu = new CMenu;
+ pMenu->m_hMenu = hMenu;
+ m_csMapLock.Lock();
+ m_mapHMENU.insert(std::make_pair(hMenu, pMenu));
+ m_csMapLock.Release();
+ pMenu->m_IsTmpMenu = TRUE;
+
+ // Ensure this thread has the TLS index set
+ TLSData* pTLSData = GetApp()->SetTlsIndex();
+ pTLSData->vTmpMenus.push_back(pMenu); // save pMenu as a smart pointer
+ return pMenu;
+ }
+#endif
+
+ inline CWnd* CWinApp::AddTmpWnd(HWND hWnd)
+ {
+ // TmpWnds are created if required to support functions like CWnd::GetParent.
+ // They are removed by CleanupTemps
+ assert(::IsWindow(hWnd));
+ assert(!GetCWndFromMap(hWnd));
+
+ CWnd* pWnd = new CWnd;
+ pWnd->m_hWnd = hWnd;
+ pWnd->AddToMap();
+ pWnd->m_IsTmpWnd = TRUE;
+
+ // Ensure this thread has the TLS index set
+ TLSData* pTLSData = GetApp()->SetTlsIndex();
+ pTLSData->vTmpWnds.push_back(pWnd); // save pWnd as a smart pointer
+ return pWnd;
+ }
+
+ inline void CWinApp::CleanupTemps()
+ // Removes all Temporary CWnds and CMenus belonging to this thread
+ {
+ // Retrieve the pointer to the TLS Data
+ TLSData* pTLSData = (TLSData*)TlsGetValue(GetApp()->GetTlsIndex());
+ assert(pTLSData);
+
+ pTLSData->vTmpDCs.clear();
+ pTLSData->vTmpGDIs.clear();
+ pTLSData->vTmpWnds.clear();
+
+
+ #ifndef _WIN32_WCE
+ pTLSData->vTmpMenus.clear();
+ #endif
+ }
+
+ inline CDC* CWinApp::GetCDCFromMap(HDC hDC)
+ {
+ // Allocate an iterator for our HWND map
+ std::map<HDC, CDC*, CompareHDC>::iterator m;
+
+ // Find the CDC pointer mapped to this HDC
+ CDC* pDC = 0;
+ m_csMapLock.Lock();
+ m = m_mapHDC.find(hDC);
+
+ if (m != m_mapHDC.end())
+ pDC = m->second;
+
+ m_csMapLock.Release();
+ return pDC;
+ }
+
+ inline CGDIObject* CWinApp::GetCGDIObjectFromMap(HGDIOBJ hObject)
+ {
+ // Allocate an iterator for our HWND map
+ std::map<HGDIOBJ, CGDIObject*, CompareGDI>::iterator m;
+
+ // Find the CGDIObject pointer mapped to this HGDIOBJ
+ CGDIObject* pObject = 0;
+ m_csMapLock.Lock();
+ m = m_mapGDI.find(hObject);
+
+ if (m != m_mapGDI.end())
+ pObject = m->second;
+
+ m_csMapLock.Release();
+ return pObject;
+ }
+
+ inline CMenu* CWinApp::GetCMenuFromMap(HMENU hMenu)
+ {
+ std::map<HMENU, CMenu*, CompareHMENU>::iterator m;
+
+ // Find the CMenu pointer mapped to this HMENU
+ CMenu* pMenu = 0;
+ m_csMapLock.Lock();
+ m = m_mapHMENU.find(hMenu);
+
+ if (m != m_mapHMENU.end())
+ pMenu = m->second;
+
+ m_csMapLock.Release();
+ return pMenu;
+ }
+
+ inline CWnd* CWinApp::GetCWndFromMap(HWND hWnd)
+ {
+ // Allocate an iterator for our HWND map
+ std::map<HWND, CWnd*, CompareHWND>::iterator m;
+
+ // Find the CWnd pointer mapped to this HWND
+ CWnd* pWnd = 0;
+ m_csMapLock.Lock();
+ m = m_mapHWND.find(hWnd);
+
+ if (m != m_mapHWND.end())
+ pWnd = m->second;
+
+ m_csMapLock.Release();
+ return pWnd;
+ }
+
+ inline BOOL CWinApp::InitInstance()
+ {
+ // InitInstance contains the initialization code for your application
+ // You should override this function with the code to run when the application starts.
+
+ // return TRUE to indicate success. FALSE will end the application
+ return TRUE;
+ }
+
+ inline int CWinApp::MessageLoop()
+ {
+ // This gets any messages queued for the application, and dispatches them.
+ MSG Msg = {0};
+ int status = 1;
+ LONG lCount = 0;
+
+ while (status != 0)
+ {
+ // While idle, perform idle processing until OnIdle returns FALSE
+ while (!::PeekMessage(&Msg, 0, 0, 0, PM_NOREMOVE) && OnIdle(lCount) == TRUE)
+ {
+ ++lCount;
+ }
+
+ lCount = 0;
+
+ // Now wait until we get a message
+ if ((status = ::GetMessage(&Msg, NULL, 0, 0)) == -1)
+ return -1;
+
+ if (!PreTranslateMessage(Msg))
+ {
+ ::TranslateMessage(&Msg);
+ ::DispatchMessage(&Msg);
+ }
+ }
+
+ return LOWORD(Msg.wParam);
+ }
+
+ inline BOOL CWinApp::OnIdle(LONG lCount)
+ {
+ if (lCount == 0)
+ CleanupTemps();
+
+ return FALSE;
+ }
+
+ inline BOOL CWinApp::PreTranslateMessage(MSG Msg)
+ {
+ // This functions is called by the MessageLoop. It processes the
+ // keyboard accelerator keys and calls CWnd::PreTranslateMessage for
+ // keyboard and mouse events.
+
+ BOOL Processed = FALSE;
+
+ // only pre-translate mouse and keyboard input events
+ if ((Msg.message >= WM_KEYFIRST && Msg.message <= WM_KEYLAST) ||
+ (Msg.message >= WM_MOUSEFIRST && Msg.message <= WM_MOUSELAST))
+ {
+ // Process keyboard accelerators
+ if (m_pWndAccel && ::TranslateAccelerator(*m_pWndAccel, m_hAccel, &Msg))
+ Processed = TRUE;
+ else
+ {
+ // Search the chain of parents for pretranslated messages.
+ for (HWND hWnd = Msg.hwnd; hWnd != NULL; hWnd = ::GetParent(hWnd))
+ {
+ CWnd* pWnd = GetCWndFromMap(hWnd);
+ if (pWnd)
+ {
+ Processed = pWnd->PreTranslateMessage(&Msg);
+ if(Processed)
+ break;
+ }
+ }
+ }
+ }
+
+ return Processed;
+ }
+
+ inline int CWinApp::Run()
+ {
+ // InitInstance runs the App's initialization code
+ if (InitInstance())
+ {
+ // Dispatch the window messages
+ return MessageLoop();
+ }
+ else
+ {
+ TRACE(_T("InitInstance failed! Terminating program\n"));
+ ::PostQuitMessage(-1);
+ return -1;
+ }
+ }
+
+ inline void CWinApp::SetAccelerators(HACCEL hAccel, CWnd* pWndAccel)
+ // nID is the resource ID of the accelerator table
+ // pWndAccel is the window pointer for translated messages
+ {
+ assert (hAccel);
+ assert (pWndAccel);
+
+ m_pWndAccel = pWndAccel;
+ m_hAccel = hAccel;
+ }
+
+ inline void CWinApp::SetCallback()
+ {
+ // Registers a temporary window class so we can get the callback
+ // address of CWnd::StaticWindowProc.
+ // This technique works for all Window versions, including WinCE.
+
+ WNDCLASS wcDefault = {0};
+
+ LPCTSTR szClassName = _T("Win32++ Temporary Window Class");
+ wcDefault.hInstance = GetInstanceHandle();
+ wcDefault.lpfnWndProc = CWnd::StaticWindowProc;
+ wcDefault.lpszClassName = szClassName;
+
+ ::RegisterClass(&wcDefault);
+
+ // Retrieve the class information
+ ZeroMemory(&wcDefault, sizeof(wcDefault));
+ ::GetClassInfo(GetInstanceHandle(), szClassName, &wcDefault);
+
+ // Save the callback address of CWnd::StaticWindowProc
+ assert(wcDefault.lpfnWndProc); // Assert fails when running UNICODE build on ANSI OS.
+ m_Callback = wcDefault.lpfnWndProc;
+ ::UnregisterClass(szClassName, GetInstanceHandle());
+ }
+
+ inline CWinApp* CWinApp::SetnGetThis(CWinApp* pThis /*= 0*/)
+ {
+ // This function stores the 'this' pointer in a static variable.
+ // Once stored, it can be used later to return the 'this' pointer.
+ // CWinApp's Destructor calls this function with a value of -1.
+
+ static CWinApp* pWinApp = 0;
+
+ if ((CWinApp*)-1 == pThis)
+ pWinApp = 0;
+ else if (0 == pWinApp)
+ pWinApp = pThis;
+
+ return pWinApp;
+ }
+
+ inline void CWinApp::SetResourceHandle(HINSTANCE hResource)
+ {
+ // This function can be used to load a resource dll.
+ // A resource dll can be used to define resources in different languages.
+ // To use this function, place code like this in InitInstance
+ //
+ // HINSTANCE hResource = LoadLibrary(_T("MyResourceDLL.dll"));
+ // SetResourceHandle(hResource);
+
+ m_hResource = hResource;
+ }
+
+ inline TLSData* CWinApp::SetTlsIndex()
+ {
+ TLSData* pTLSData = (TLSData*)::TlsGetValue(GetTlsIndex());
+ if (NULL == pTLSData)
+ {
+ pTLSData = new TLSData;
+
+ m_csTLSLock.Lock();
+ m_vTLSData.push_back(pTLSData); // store as a Shared_Ptr
+ m_csTLSLock.Release();
+
+ ::TlsSetValue(GetTlsIndex(), pTLSData);
+ }
+
+ return pTLSData;
+ }
+
+
+ ////////////////////////////////////////
+ // Definitions for the CWnd class
+ //
+ inline CWnd::CWnd() : m_hWnd(NULL), m_PrevWindowProc(NULL), m_IsTmpWnd(FALSE)
+ {
+ // Note: m_hWnd is set in CWnd::CreateEx(...)
+ m_pcs = new CREATESTRUCT; // store the CREATESTRICT in a smart pointer
+ m_pwc = new WNDCLASS; // store the WNDCLASS in a smart pointer
+ ::ZeroMemory(m_pcs.get(), sizeof(CREATESTRUCT));
+ ::ZeroMemory(m_pwc.get(), sizeof(WNDCLASS));
+ }
+
+ inline CWnd::~CWnd()
+ {
+ // Destroys the window for this object and cleans up resources.
+ Destroy();
+ }
+
+ inline void CWnd::AddToMap()
+ // Store the window handle and CWnd pointer in the HWND map
+ {
+ assert( GetApp() );
+ GetApp()->m_csMapLock.Lock();
+
+ assert(::IsWindow(m_hWnd));
+ assert(!GetApp()->GetCWndFromMap(m_hWnd));
+
+ GetApp()->m_mapHWND.insert(std::make_pair(m_hWnd, this));
+ GetApp()->m_csMapLock.Release();
+ }
+
+ inline BOOL CWnd::Attach(HWND hWnd)
+ // Subclass an existing window and attach it to a CWnd
+ {
+ assert( GetApp() );
+ assert(::IsWindow(hWnd));
+
+ // Ensure this thread has the TLS index set
+ // Note: Perform the attach from the same thread as the window's message loop
+ GetApp()->SetTlsIndex();
+
+ if (m_PrevWindowProc)
+ Detach();
+
+ Subclass(hWnd);
+
+ // Store the CWnd pointer in the HWND map
+ AddToMap();
+ OnCreate();
+ OnInitialUpdate();
+
+ return TRUE;
+ }
+
+ inline BOOL CWnd::AttachDlgItem(UINT nID, CWnd* pParent)
+ // Converts a dialog item to a CWnd object
+ {
+ assert(pParent->IsWindow());
+
+ HWND hWnd = ::GetDlgItem(pParent->GetHwnd(), nID);
+ return Attach(hWnd);
+ }
+
+ inline void CWnd::CenterWindow() const
+ // Centers this window over it's parent
+ {
+
+ // required for multi-monitor support with Dev-C++ and VC6
+ #ifndef _WIN32_WCE
+ #ifndef MONITOR_DEFAULTTONEAREST
+ #define MONITOR_DEFAULTTONEAREST 0x00000002
+ #endif
+ #ifndef HMONITOR
+ DECLARE_HANDLE(HMONITOR);
+ #endif
+ #ifndef MONITORINFO
+ typedef struct tagMONITORINFO
+ {
+ DWORD cbSize;
+ RECT rcMonitor;
+ RECT rcWork;
+ DWORD dwFlags;
+ } MONITORINFO, *LPMONITORINFO;
+ #endif // MONITOR_DEFAULTTONEAREST
+ #endif // _WIN32_WCE
+
+ assert(::IsWindow(m_hWnd));
+
+ CRect rc = GetWindowRect();
+ CRect rcParent;
+ CRect rcDesktop;
+
+ // Get screen dimensions excluding task bar
+ ::SystemParametersInfo(SPI_GETWORKAREA, 0, &rcDesktop, 0);
+
+ // Get the parent window dimensions (parent could be the desktop)
+ if (GetParent() != NULL) rcParent = GetParent()->GetWindowRect();
+ else rcParent = rcDesktop;
+
+ #ifndef _WIN32_WCE
+ // Import the GetMonitorInfo and MonitorFromWindow functions
+ HMODULE hUser32 = LoadLibrary(_T("USER32.DLL"));
+ typedef BOOL (WINAPI* LPGMI)(HMONITOR hMonitor, LPMONITORINFO lpmi);
+ typedef HMONITOR (WINAPI* LPMFW)(HWND hwnd, DWORD dwFlags);
+ LPMFW pfnMonitorFromWindow = (LPMFW)::GetProcAddress(hUser32, "MonitorFromWindow");
+ #ifdef _UNICODE
+ LPGMI pfnGetMonitorInfo = (LPGMI)::GetProcAddress(hUser32, "GetMonitorInfoW");
+ #else
+ LPGMI pfnGetMonitorInfo = (LPGMI)::GetProcAddress(hUser32, "GetMonitorInfoA");
+ #endif
+
+ // Take multi-monitor systems into account
+ if (pfnGetMonitorInfo && pfnMonitorFromWindow)
+ {
+ HMONITOR hActiveMonitor = pfnMonitorFromWindow(m_hWnd, MONITOR_DEFAULTTONEAREST);
+ MONITORINFO mi = { sizeof(mi), 0};
+
+ if(pfnGetMonitorInfo(hActiveMonitor, &mi))
+ {
+ rcDesktop = mi.rcWork;
+ if (GetParent() == NULL) rcParent = mi.rcWork;
+ }
+ }
+ FreeLibrary(hUser32);
+ #endif
+
+ // Calculate point to center the dialog over the portion of parent window on this monitor
+ rcParent.IntersectRect(rcParent, rcDesktop);
+ int x = rcParent.left + (rcParent.Width() - rc.Width())/2;
+ int y = rcParent.top + (rcParent.Height() - rc.Height())/2;
+
+ // Keep the dialog wholly on the monitor display
+ x = (x < rcDesktop.left)? rcDesktop.left : x;
+ x = (x > rcDesktop.right - rc.Width())? rcDesktop.right - rc.Width() : x;
+ y = (y < rcDesktop.top) ? rcDesktop.top: y;
+ y = (y > rcDesktop.bottom - rc.Height())? rcDesktop.bottom - rc.Height() : y;
+
+ SetWindowPos(HWND_TOP, x, y, 0, 0, SWP_NOSIZE);
+ }
+
+ inline void CWnd::Cleanup()
+ // Returns the CWnd to its default state
+ {
+ if ( GetApp() ) RemoveFromMap();
+ m_hWnd = NULL;
+ m_PrevWindowProc = NULL;
+ m_IsTmpWnd = FALSE;
+ }
+
+ inline HWND CWnd::Create(CWnd* pParent /* = NULL */)
+ // Creates the window. This is the default method of window creation.
+ {
+
+ // Test if Win32++ has been started
+ assert( GetApp() );
+
+ // Set the WNDCLASS parameters
+ PreRegisterClass(*m_pwc);
+ if (m_pwc->lpszClassName)
+ {
+ RegisterClass(*m_pwc);
+ m_pcs->lpszClass = m_pwc->lpszClassName;
+ }
+
+ // Set the CREATESTRUCT parameters
+ PreCreate(*m_pcs);
+
+ // Set the Window Class Name
+ if (!m_pcs->lpszClass)
+ m_pcs->lpszClass = _T("Win32++ Window");
+
+ // Set Parent
+ HWND hWndParent = pParent? pParent->GetHwnd() : 0;
+ if (!hWndParent && m_pcs->hwndParent)
+ hWndParent = m_pcs->hwndParent;
+
+ // Set the window style
+ DWORD dwStyle;
+ DWORD dwOverlappedStyle = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX;
+ if (m_pcs->style)
+ dwStyle = m_pcs->style;
+ else
+ dwStyle = WS_VISIBLE | ((hWndParent)? WS_CHILD : dwOverlappedStyle);
+
+ // Set window size and position
+ int x = (m_pcs->cx || m_pcs->cy)? m_pcs->x : CW_USEDEFAULT;
+ int cx = (m_pcs->cx || m_pcs->cy)? m_pcs->cx : CW_USEDEFAULT;
+ int y = (m_pcs->cx || m_pcs->cy)? m_pcs->y : CW_USEDEFAULT;
+ int cy = (m_pcs->cx || m_pcs->cy)? m_pcs->cy : CW_USEDEFAULT;
+
+ // Create the window
+#ifndef _WIN32_WCE
+ CreateEx(m_pcs->dwExStyle, m_pcs->lpszClass, m_pcs->lpszName, dwStyle, x, y,
+ cx, cy, pParent, FromHandle(m_pcs->hMenu), m_pcs->lpCreateParams);
+#else
+ CreateEx(m_pcs->dwExStyle, m_pcs->lpszClass, m_pcs->lpszName, dwStyle, x, y,
+ cx, cy, pParent, 0, m_pcs->lpCreateParams);
+#endif
+
+ return m_hWnd;
+ }
+
+ inline HWND CWnd::CreateEx(DWORD dwExStyle, LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rc, CWnd* pParent, CMenu* pMenu, LPVOID lpParam /*= NULL*/)
+ // Creates the window by specifying all the window creation parameters
+ {
+ int x = rc.left;
+ int y = rc.top;
+ int cx = rc.right - rc.left;
+ int cy = rc.bottom - rc.top;
+ return CreateEx(dwExStyle, lpszClassName, lpszWindowName, dwStyle, x, y, cx, cy, pParent, pMenu, lpParam);
+ }
+
+ inline HWND CWnd::CreateEx(DWORD dwExStyle, LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, int x, int y, int nWidth, int nHeight, CWnd* pParent, CMenu* pMenu, LPVOID lpParam /*= NULL*/)
+ // Creates the window by specifying all the window creation parameters
+ {
+
+ assert( GetApp() ); // Test if Win32++ has been started
+ assert(!::IsWindow(m_hWnd)); // Only one window per CWnd instance allowed
+
+ try
+ {
+ // Prepare the CWnd if it has been reused
+ Destroy();
+
+ // Ensure a window class is registered
+ std::vector<TCHAR> vTChar( MAX_STRING_SIZE+1, _T('\0') );
+ TCHAR* ClassName = &vTChar[0];
+ if (0 == lpszClassName || 0 == lstrlen(lpszClassName) )
+ lstrcpyn (ClassName, _T("Win32++ Window"), MAX_STRING_SIZE);
+ else
+ // Create our own local copy of szClassName.
+ lstrcpyn(ClassName, lpszClassName, MAX_STRING_SIZE);
+
+ WNDCLASS wc = {0};
+ wc.lpszClassName = ClassName;
+ wc.hbrBackground = (HBRUSH)::GetStockObject(WHITE_BRUSH);
+ wc.hCursor = ::LoadCursor(NULL, IDC_ARROW);
+
+ // Register the window class (if not already registered)
+ if (!RegisterClass(wc))
+ throw CWinException(_T("Failed to register window class"));
+
+ HWND hWndParent = pParent? pParent->GetHwnd() : 0;
+
+ // Ensure this thread has the TLS index set
+ TLSData* pTLSData = GetApp()->SetTlsIndex();
+
+ // Store the CWnd pointer in thread local storage
+ pTLSData->pCWnd = this;
+
+ // Create window
+#ifdef _WIN32_WCE
+ m_hWnd = ::CreateWindowEx(dwExStyle, ClassName, lpszWindowName, dwStyle, x, y, nWidth, nHeight,
+ hWndParent, 0, GetApp()->GetInstanceHandle(), lpParam);
+#else
+ HMENU hMenu = pMenu? pMenu->GetHandle() : NULL;
+ m_hWnd = ::CreateWindowEx(dwExStyle, ClassName, lpszWindowName, dwStyle, x, y, nWidth, nHeight,
+ hWndParent, hMenu, GetApp()->GetInstanceHandle(), lpParam);
+#endif
+
+ // Now handle window creation failure
+ if (!m_hWnd)
+ throw CWinException(_T("Failed to Create Window"));
+
+ // Automatically subclass predefined window class types
+ ::GetClassInfo(GetApp()->GetInstanceHandle(), lpszClassName, &wc);
+ if (wc.lpfnWndProc != GetApp()->m_Callback)
+ {
+ Subclass(m_hWnd);
+
+ // Send a message to force the HWND to be added to the map
+ SendMessage(WM_NULL, 0L, 0L);
+
+ OnCreate(); // We missed the WM_CREATE message, so call OnCreate now
+ }
+
+ // Clear the CWnd pointer from TLS
+ pTLSData->pCWnd = NULL;
+ }
+
+ catch (const CWinException &e)
+ {
+ TRACE(_T("\n*** Failed to create window ***\n"));
+ e.what(); // Display the last error message.
+
+ // eat the exception (don't rethrow)
+ }
+
+ // Window creation is complete. Now call OnInitialUpdate
+ OnInitialUpdate();
+
+ return m_hWnd;
+ }
+
+ inline void CWnd::Destroy()
+ // Destroys the window and returns the CWnd back to its default state, ready for reuse.
+ {
+ if (m_IsTmpWnd)
+ m_hWnd = NULL;
+
+ if (IsWindow())
+ ::DestroyWindow(m_hWnd);
+
+ // Return the CWnd to its default state
+ Cleanup();
+ }
+
+ inline HWND CWnd::Detach()
+ // Reverse an Attach
+ {
+ assert(::IsWindow(m_hWnd));
+ assert(0 != m_PrevWindowProc); // Only a subclassed window can be detached
+
+ SetWindowLongPtr(GWLP_WNDPROC, (LONG_PTR)m_PrevWindowProc);
+ HWND hWnd = m_hWnd;
+ Cleanup();
+
+ return hWnd;
+ }
+
+ inline LRESULT CWnd::FinalWindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
+ // Pass messages on to the appropriate default window procedure
+ // CMDIChild and CMDIFrame override this function
+ {
+ return ::DefWindowProc(m_hWnd, uMsg, wParam, lParam);
+ }
+
+ inline CWnd* CWnd::GetAncestor(UINT gaFlags /*= GA_ROOTOWNER*/) const
+ // The GetAncestor function retrieves a pointer to the ancestor (root parent)
+ // of the window. Supports Win95.
+ {
+ assert(::IsWindow(m_hWnd));
+ HWND hWnd;
+
+#if (WINVER < 0x0500) // Win2000 and above
+ UNREFERENCED_PARAMETER(gaFlags);
+ hWnd = m_hWnd;
+ HWND hWndParent = ::GetParent(hWnd);
+ while (::IsChild(hWndParent, hWnd))
+ {
+ hWnd = hWndParent;
+ hWndParent = ::GetParent(hWnd);
+ }
+#else
+ hWnd = ::GetAncestor(m_hWnd, gaFlags);
+#endif
+
+ return FromHandle(hWnd);
+
+ }
+
+ inline CString CWnd::GetClassName() const
+ // Retrieves the name of the class to which the specified window belongs.
+ {
+ assert(::IsWindow(m_hWnd));
+
+ CString str;
+ LPTSTR szStr = str.GetBuffer(MAX_STRING_SIZE+1);
+ ::GetClassName(m_hWnd, szStr, MAX_STRING_SIZE+1);
+ str.ReleaseBuffer();
+ return str;
+ }
+
+ inline CString CWnd::GetDlgItemText(int nIDDlgItem) const
+ // Retrieves the title or text associated with a control in a dialog box.
+ {
+ assert(::IsWindow(m_hWnd));
+
+ int nLength = ::GetWindowTextLength(::GetDlgItem(m_hWnd, nIDDlgItem));
+ CString str;
+ LPTSTR szStr = str.GetBuffer(nLength+1);
+ ::GetDlgItemText(m_hWnd, nIDDlgItem, szStr, nLength+1);
+ str.ReleaseBuffer();
+ return str;
+ }
+
+ inline CString CWnd::GetWindowText() const
+ // Retrieves the text of the window's title bar.
+ {
+ assert(::IsWindow(m_hWnd));
+
+ int nLength = ::GetWindowTextLength(m_hWnd);
+ CString str;
+ LPTSTR szStr = str.GetBuffer(nLength+1);
+ ::GetWindowText(m_hWnd, szStr, nLength+1);
+ str.ReleaseBuffer();
+ return str;
+ }
+
+ inline BOOL CWnd::OnCommand(WPARAM wParam, LPARAM lParam)
+ {
+ UNREFERENCED_PARAMETER(wParam);
+ UNREFERENCED_PARAMETER(lParam);
+
+ // Override this to handle WM_COMMAND messages, for example
+
+ // switch (LOWORD(wParam))
+ // {
+ // case IDM_FILE_NEW:
+ // OnFileNew();
+ // TRUE; // return TRUE for handled commands
+ // }
+
+ // return FALSE for unhandled commands
+ return FALSE;
+ }
+
+ inline void CWnd::OnCreate()
+ {
+ // This function is called when a WM_CREATE message is recieved
+ // Override it in your derived class to automatically perform tasks
+ // during window creation.
+ }
+
+ inline void CWnd::OnDraw(CDC* pDC)
+ // Called when part of the client area of the window needs to be drawn
+ {
+ UNREFERENCED_PARAMETER(pDC);
+
+ // Override this function in your derived class to perform drawing tasks.
+ }
+
+ inline BOOL CWnd::OnEraseBkgnd(CDC* pDC)
+ // Called when the background of the window's client area needs to be erased.
+ {
+ UNREFERENCED_PARAMETER(pDC);
+
+ // Override this function in your derived class to perform drawing tasks.
+
+ // Return Value: Return FALSE to also permit default erasure of the background
+ // Return TRUE to prevent default erasure of the background
+
+ return FALSE;
+ }
+
+
+ inline void CWnd::OnInitialUpdate()
+ {
+ // This function is called automatically once the window is created
+ // Override it in your derived class to automatically perform tasks
+ // after window creation.
+ }
+
+ inline LRESULT CWnd::MessageReflect(HWND hWndParent, UINT uMsg, WPARAM wParam, LPARAM lParam)
+ {
+ // A function used to call OnMessageReflect. You shouldn't need to call or
+ // override this function.
+
+ HWND hWnd = NULL;
+ switch (uMsg)
+ {
+ case WM_COMMAND:
+ case WM_CTLCOLORBTN:
+ case WM_CTLCOLOREDIT:
+ case WM_CTLCOLORDLG:
+ case WM_CTLCOLORLISTBOX:
+ case WM_CTLCOLORSCROLLBAR:
+ case WM_CTLCOLORSTATIC:
+ case WM_CHARTOITEM:
+ case WM_VKEYTOITEM:
+ case WM_HSCROLL:
+ case WM_VSCROLL:
+ hWnd = (HWND)lParam;
+ break;
+
+ case WM_DRAWITEM:
+ case WM_MEASUREITEM:
+ case WM_DELETEITEM:
+ case WM_COMPAREITEM:
+ hWnd = ::GetDlgItem(hWndParent, (int)wParam);
+ break;
+
+ case WM_PARENTNOTIFY:
+ switch(LOWORD(wParam))
+ {
+ case WM_CREATE:
+ case WM_DESTROY:
+ hWnd = (HWND)lParam;
+ break;
+ }
+ }
+
+ CWnd* Wnd = GetApp()->GetCWndFromMap(hWnd);
+
+ if (Wnd != NULL)
+ return Wnd->OnMessageReflect(uMsg, wParam, lParam);
+
+ return 0L;
+ }
+
+ inline LRESULT CWnd::OnMessageReflect(UINT uMsg, WPARAM wParam, LPARAM lParam)
+ {
+ UNREFERENCED_PARAMETER(uMsg);
+ UNREFERENCED_PARAMETER(wParam);
+ UNREFERENCED_PARAMETER(lParam);
+ // This function processes those special messages (see above) sent
+ // by some older controls, and reflects them back to the originating CWnd object.
+ // Override this function in your derrived class to handle these special messages.
+
+ // Your overriding function should look like this ...
+
+ // switch (uMsg)
+ // {
+ // Handle your reflected messages here
+ // }
+
+ // return 0L for unhandled messages
+ return 0L;
+ }
+
+ inline LRESULT CWnd::OnNotify(WPARAM wParam, LPARAM lParam)
+ {
+ UNREFERENCED_PARAMETER(wParam);
+ UNREFERENCED_PARAMETER(lParam);
+
+ // You can use either OnNotifyReflect or OnNotify to handle notifications
+ // Override OnNotifyReflect to handle notifications in the CWnd class that
+ // generated the notification. OR
+ // Override OnNotify to handle notifications in the PARENT of the CWnd class
+ // that generated the notification.
+
+ // Your overriding function should look like this ...
+
+ // switch (((LPNMHDR)lParam)->code)
+ // {
+ // Handle your notifications from the CHILD window here
+ // Return the value recommended by the Windows API documentation.
+ // For many notifications, the return value doesn't matter, but for some it does.
+ // }
+
+ // return 0L for unhandled notifications
+ return 0L;
+ }
+
+ inline LRESULT CWnd::OnNotifyReflect(WPARAM wParam, LPARAM lParam)
+ {
+ UNREFERENCED_PARAMETER(wParam);
+ UNREFERENCED_PARAMETER(lParam);
+
+ // Override OnNotifyReflect to handle notifications in the CWnd class that
+ // generated the notification.
+
+ // Your overriding function should look like this ...
+
+ // switch (((LPNMHDR)lParam)->code)
+ // {
+ // Handle your notifications from this window here
+ // Return the value recommended by the Windows API documentation.
+ // }
+
+ // return 0L for unhandled notifications
+ return 0L;
+ }
+
+ inline void CWnd::OnMenuUpdate(UINT nID)
+ // Called when menu items are about to be displayed
+ {
+ UNREFERENCED_PARAMETER(nID);
+
+ // Override this function to modify the behaviour of menu items,
+ // such as adding or removing checkmarks
+ }
+
+ inline void CWnd::PreCreate(CREATESTRUCT& cs)
+ // Called by CWnd::Create to set some window parameters
+ {
+ // Test if Win32++ has been started
+ assert(GetApp()); // Test if Win32++ has been started
+
+ m_pcs->cx = cs.cx;
+ m_pcs->cy = cs.cy;
+ m_pcs->dwExStyle = cs.dwExStyle;
+ m_pcs->hInstance = GetApp()->GetInstanceHandle();
+ m_pcs->hMenu = cs.hMenu;
+ m_pcs->hwndParent = cs.hwndParent;
+ m_pcs->lpCreateParams = cs.lpCreateParams;
+ m_pcs->lpszClass = cs.lpszClass;
+ m_pcs->lpszName = cs.lpszName;
+ m_pcs->style = cs.style;
+ m_pcs->x = cs.x;
+ m_pcs->y = cs.y;
+
+ // Overide this function in your derived class to set the
+ // CREATESTRUCT values prior to window creation.
+ // The cs.lpszClass parameter should NOT be specified if the
+ // PreRegisterClass function is used to create a window class.
+ }
+
+ inline void CWnd::PreRegisterClass(WNDCLASS& wc)
+ // Called by CWnd::Create to set some window parameters
+ // Useful for setting the background brush and cursor
+ {
+ // Test if Win32++ has been started
+ assert( GetApp() );
+
+ m_pwc->style = wc.style;
+ m_pwc->lpfnWndProc = CWnd::StaticWindowProc;
+ m_pwc->cbClsExtra = wc.cbClsExtra;
+ m_pwc->cbWndExtra = wc.cbWndExtra;
+ m_pwc->hInstance = GetApp()->GetInstanceHandle();
+ m_pwc->hIcon = wc.hIcon;
+ m_pwc->hCursor = wc.hCursor;
+ m_pwc->hbrBackground = wc.hbrBackground;
+ m_pwc->lpszMenuName = wc.lpszMenuName;
+ m_pwc->lpszClassName = wc.lpszClassName;
+
+ // Overide this function in your derived class to set the
+ // WNDCLASS values prior to window creation.
+
+ // ADDITIONAL NOTES:
+ // 1) The lpszClassName must be set for this function to take effect.
+ // 2) The lpfnWndProc is always CWnd::StaticWindowProc.
+ // 3) No other defaults are set, so the following settings might prove useful
+ // wc.hCursor = ::LoadCursor(NULL, IDC_ARROW);
+ // wc.hbrBackground = (HBRUSH)::GetStockObject(WHITE_BRUSH);
+ // wc.hIcon = ::LoadIcon(NULL, IDI_APPLICATION);
+ // 4) The styles that can be set here are WNDCLASS styles. These are a different
+ // set of styles to those set by CREATESTRUCT (used in PreCreate).
+ // 5) RegisterClassEx is not used because its not supported on WinCE.
+ // To set a small icon for the window, use SetIconSmall.
+ }
+
+ inline BOOL CWnd::PreTranslateMessage(MSG* pMsg)
+ {
+ UNREFERENCED_PARAMETER(pMsg);
+
+ // Override this function if your class requires input messages to be
+ // translated before normal processing. Function which translate messages
+ // include TranslateAccelerator, TranslateMDISysAccel and IsDialogMessage.
+ // Return TRUE if the message is translated.
+
+ return FALSE;
+ }
+
+ inline BOOL CWnd::RegisterClass(WNDCLASS& wc)
+ // A private function used by the PreRegisterClass function to register a
+ // window class prior to window creation
+ {
+ assert( GetApp() );
+ assert( (0 != lstrlen(wc.lpszClassName) && ( lstrlen(wc.lpszClassName) <= MAX_STRING_SIZE) ) );
+
+ // Check to see if this classname is already registered
+ WNDCLASS wcTest = {0};
+ BOOL Done = FALSE;
+
+ if (::GetClassInfo(GetApp()->GetInstanceHandle(), wc.lpszClassName, &wcTest))
+ {
+ wc = wcTest;
+ Done = TRUE;
+ }
+
+ if (!Done)
+ {
+ // Set defaults
+ wc.hInstance = GetApp()->GetInstanceHandle();
+ wc.lpfnWndProc = CWnd::StaticWindowProc;
+
+ // Register the WNDCLASS structure
+ if ( !::RegisterClass(&wc) )
+ throw CWinException(_T("Failed to register window class"));
+
+ Done = TRUE;
+ }
+
+ return Done;
+ }
+
+ inline BOOL CWnd::RemoveFromMap()
+ {
+ BOOL Success = FALSE;
+
+ if (GetApp())
+ {
+
+ // Allocate an iterator for our HWND map
+ std::map<HWND, CWnd*, CompareHWND>::iterator m;
+
+ CWinApp* pApp = GetApp();
+ if (pApp)
+ {
+ // Erase the CWnd pointer entry from the map
+ pApp->m_csMapLock.Lock();
+ for (m = pApp->m_mapHWND.begin(); m != pApp->m_mapHWND.end(); ++m)
+ {
+ if (this == m->second)
+ {
+ pApp->m_mapHWND.erase(m);
+ Success = TRUE;
+ break;
+ }
+ }
+
+ pApp->m_csMapLock.Release();
+ }
+ }
+
+ return Success;
+ }
+
+ inline HICON CWnd::SetIconLarge(int nIcon)
+ // Sets the large icon associated with the window
+ {
+ assert( GetApp() );
+ assert(::IsWindow(m_hWnd));
+
+ HICON hIconLarge = (HICON) (::LoadImage (GetApp()->GetResourceHandle(), MAKEINTRESOURCE (nIcon), IMAGE_ICON,
+ ::GetSystemMetrics (SM_CXICON), ::GetSystemMetrics (SM_CYICON), 0));
+
+ if (hIconLarge)
+ SendMessage (WM_SETICON, WPARAM (ICON_BIG), LPARAM (hIconLarge));
+ else
+ TRACE(_T("**WARNING** SetIconLarge Failed\n"));
+
+ return hIconLarge;
+ }
+
+ inline HICON CWnd::SetIconSmall(int nIcon)
+ // Sets the small icon associated with the window
+ {
+ assert( GetApp() );
+ assert(::IsWindow(m_hWnd));
+
+ HICON hIconSmall = (HICON) (::LoadImage (GetApp()->GetResourceHandle(), MAKEINTRESOURCE (nIcon), IMAGE_ICON,
+ ::GetSystemMetrics (SM_CXSMICON), ::GetSystemMetrics (SM_CYSMICON), 0));
+
+ if (hIconSmall)
+ SendMessage (WM_SETICON, WPARAM (ICON_SMALL), LPARAM (hIconSmall));
+ else
+ TRACE(_T("**WARNING** SetIconSmall Failed\n"));
+
+ return hIconSmall;
+ }
+
+ inline LRESULT CALLBACK CWnd::StaticWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+ // All CWnd windows direct their messages here. This function redirects the message
+ // to the CWnd's WndProc function.
+ {
+ assert( GetApp() );
+
+ CWnd* w = GetApp()->GetCWndFromMap(hWnd);
+ if (0 == w)
+ {
+ // The CWnd pointer wasn't found in the map, so add it now
+
+ // Retrieve the pointer to the TLS Data
+ TLSData* pTLSData = (TLSData*)TlsGetValue(GetApp()->GetTlsIndex());
+ assert(pTLSData);
+
+ // Retrieve pointer to CWnd object from Thread Local Storage TLS
+ w = pTLSData->pCWnd;
+ assert(w); // pTLSData->pCWnd is assigned in CreateEx
+ pTLSData->pCWnd = NULL;
+
+ // Store the CWnd pointer in the HWND map
+ w->m_hWnd = hWnd;
+ w->AddToMap();
+ }
+
+ return w->WndProc(uMsg, wParam, lParam);
+
+ } // LRESULT CALLBACK StaticWindowProc(...)
+
+ inline void CWnd::Subclass(HWND hWnd)
+ // A private function used by CreateEx, Attach and AttachDlgItem
+ {
+ assert(::IsWindow(hWnd));
+
+ m_PrevWindowProc = (WNDPROC)::SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)CWnd::StaticWindowProc);
+ m_hWnd = hWnd;
+ }
+
+ inline LRESULT CWnd::WndProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
+ {
+ // Override this function in your class derrived from CWnd to handle
+ // window messages. A typical function might look like this:
+
+ // switch (uMsg)
+ // {
+ // case MESSAGE1: // Some Windows API message
+ // OnMessage1(); // A user defined function
+ // break; // Also do default processing
+ // case MESSAGE2:
+ // OnMessage2();
+ // return x; // Don't do default processing, but instead return
+ // // a value recommended by the Windows API documentation
+ // }
+
+ // Always pass unhandled messages on to WndProcDefault
+ return WndProcDefault(uMsg, wParam, lParam);
+ }
+
+ inline LRESULT CWnd::WndProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam)
+ // All WndProc functions should pass unhandled window messages to this function
+ {
+ LRESULT lr = 0L;
+
+ switch (uMsg)
+ {
+ case UWM_CLEANUPTEMPS:
+ {
+ TLSData* pTLSData = (TLSData*)TlsGetValue(GetApp()->GetTlsIndex());
+ pTLSData->vTmpWnds.clear();
+ }
+ break;
+ case WM_COMMAND:
+ {
+ // Refelect this message if it's from a control
+ CWnd* pWnd = GetApp()->GetCWndFromMap((HWND)lParam);
+ if (pWnd != NULL)
+ lr = pWnd->OnCommand(wParam, lParam);
+
+ // Handle user commands
+ if (!lr)
+ lr = OnCommand(wParam, lParam);
+
+ if (lr) return 0L;
+ }
+ break; // Note: Some MDI commands require default processing
+ case WM_CREATE:
+ OnCreate();
+ break;
+ // An example of how to end the application when the window closes
+ // If needed, put this in the class you inherit from CWnd
+ // case WM_DESTROY:
+ // ::PostQuitMessage(0);
+ // return 0L;
+ case WM_NOTIFY:
+ {
+ // Do Notification reflection if it came from a CWnd object
+ HWND hwndFrom = ((LPNMHDR)lParam)->hwndFrom;
+ CWnd* pWndFrom = GetApp()->GetCWndFromMap(hwndFrom);
+
+ if (lstrcmp(GetClassName(), _T("ReBarWindow32")) != 0) // Skip notification reflection for rebars to avoid double handling
+ {
+ if (pWndFrom != NULL)
+ lr = pWndFrom->OnNotifyReflect(wParam, lParam);
+ else
+ {
+ // Some controls (eg ListView) have child windows.
+ // Reflect those notifications too.
+ CWnd* pWndFromParent = GetApp()->GetCWndFromMap(::GetParent(hwndFrom));
+ if (pWndFromParent != NULL)
+ lr = pWndFromParent->OnNotifyReflect(wParam, lParam);
+ }
+ }
+
+ // Handle user notifications
+ if (!lr) lr = OnNotify(wParam, lParam);
+ if (lr) return lr;
+ }
+ break;
+
+ case WM_PAINT:
+ {
+ // Subclassed controls expect to do their own painting.
+ // CustomDraw or OwnerDraw are normally used to modify the drawing of controls.
+ if (m_PrevWindowProc) break;
+
+ if (::GetUpdateRect(m_hWnd, NULL, FALSE))
+ {
+ CPaintDC dc(this);
+ OnDraw(&dc);
+ }
+ else
+ // RedrawWindow can require repainting without an update rect
+ {
+ CClientDC dc(this);
+ OnDraw(&dc);
+ }
+ }
+ return 0L;
+
+ case WM_ERASEBKGND:
+ {
+ CDC dc((HDC)wParam);
+ BOOL bResult = OnEraseBkgnd(&dc);
+ dc.Detach();
+ if (bResult) return TRUE;
+ }
+ break;
+
+ // A set of messages to be reflected back to the control that generated them
+ case WM_CTLCOLORBTN:
+ case WM_CTLCOLOREDIT:
+ case WM_CTLCOLORDLG:
+ case WM_CTLCOLORLISTBOX:
+ case WM_CTLCOLORSCROLLBAR:
+ case WM_CTLCOLORSTATIC:
+ case WM_DRAWITEM:
+ case WM_MEASUREITEM:
+ case WM_DELETEITEM:
+ case WM_COMPAREITEM:
+ case WM_CHARTOITEM:
+ case WM_VKEYTOITEM:
+ case WM_HSCROLL:
+ case WM_VSCROLL:
+ case WM_PARENTNOTIFY:
+ {
+ // if (m_PrevWindowProc) break; // Suppress for subclassed windows
+
+ LRESULT lr = MessageReflect(m_hWnd, uMsg, wParam, lParam);
+ if (lr) return lr; // Message processed so return
+ }
+ break; // Do default processing when message not already processed
+
+ case UWM_UPDATE_COMMAND:
+ OnMenuUpdate((UINT)wParam); // Perform menu updates
+ break;
+
+ } // switch (uMsg)
+
+ // Now hand all messages to the default procedure
+ if (m_PrevWindowProc)
+ return ::CallWindowProc(m_PrevWindowProc, m_hWnd, uMsg, wParam, lParam);
+ else
+ return FinalWindowProc(uMsg, wParam, lParam);
+
+ } // LRESULT CWnd::WindowProc(...)
+
+
+ //
+ // Wrappers for Win32 API functions
+ //
+
+ inline CDC* CWnd::BeginPaint(PAINTSTRUCT& ps) const
+ // The BeginPaint function prepares the specified window for painting and fills a PAINTSTRUCT structure with
+ // information about the painting.
+ {
+ assert(::IsWindow(m_hWnd));
+ return FromHandle(::BeginPaint(m_hWnd, &ps));
+ }
+
+ inline BOOL CWnd::BringWindowToTop() const
+ // The BringWindowToTop function brings the specified window to the top
+ // of the Z order. If the window is a top-level window, it is activated.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ::BringWindowToTop(m_hWnd);
+ }
+
+ inline LRESULT CWnd::CallWindowProc(WNDPROC lpPrevWndFunc, UINT Msg, WPARAM wParam, LPARAM lParam) const
+ {
+ assert(::IsWindow(m_hWnd));
+ return ::CallWindowProc(lpPrevWndFunc, m_hWnd, Msg, wParam, lParam);
+ }
+
+ inline BOOL CWnd::CheckDlgButton(int nIDButton, UINT uCheck) const
+ // The CheckDlgButton function changes the check state of a button control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ::CheckDlgButton(m_hWnd, nIDButton, uCheck);
+ }
+
+ inline BOOL CWnd::CheckRadioButton(int nIDFirstButton, int nIDLastButton, int nIDCheckButton) const
+ // The CheckRadioButton function adds a check mark to (checks) a specified radio button in a group
+ // and removes a check mark from (clears) all other radio buttons in the group.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ::CheckRadioButton(m_hWnd, nIDFirstButton, nIDLastButton, nIDCheckButton);
+ }
+
+ inline CWnd* CWnd::ChildWindowFromPoint(POINT pt) const
+ // determines which, if any, of the child windows belonging to a parent window contains
+ // the specified point. The search is restricted to immediate child windows.
+ // Grandchildren, and deeper descendant windows are not searched.
+ {
+ assert(::IsWindow(m_hWnd));
+ return FromHandle(::ChildWindowFromPoint(m_hWnd, pt));
+ }
+
+ inline BOOL CWnd::ClientToScreen(POINT& pt) const
+ // The ClientToScreen function converts the client-area coordinates of a specified point to screen coordinates.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ::ClientToScreen(m_hWnd, &pt);
+ }
+
+ inline BOOL CWnd::ClientToScreen(RECT& rc) const
+ // The ClientToScreen function converts the client-area coordinates of a specified RECT to screen coordinates.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (BOOL)::MapWindowPoints(m_hWnd, NULL, (LPPOINT)&rc, 2);
+ }
+
+ inline HDWP CWnd::DeferWindowPos(HDWP hWinPosInfo, HWND hWndInsertAfter, int x, int y, int cx, int cy, UINT uFlags) const
+ // The DeferWindowPos function updates the specified multiple-window – position structure for the window.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ::DeferWindowPos(hWinPosInfo, m_hWnd, hWndInsertAfter, x, y, cx, cy, uFlags);
+ }
+
+ inline HDWP CWnd::DeferWindowPos(HDWP hWinPosInfo, HWND hWndInsertAfter, const RECT& rc, UINT uFlags) const
+ // The DeferWindowPos function updates the specified multiple-window – position structure for the window.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ::DeferWindowPos(hWinPosInfo, m_hWnd, hWndInsertAfter, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, uFlags);
+ }
+
+ inline LRESULT CWnd::DefWindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam) const
+ // This function provides default processing for any window messages that an application does not process.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ::DefWindowProc(m_hWnd, uMsg, wParam, lParam);
+ }
+
+ inline BOOL CWnd::DrawMenuBar() const
+ // The DrawMenuBar function redraws the menu bar of the specified window. If the menu bar changes after
+ // the system has created the window, this function must be called to draw the changed menu bar.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ::DrawMenuBar(m_hWnd);
+ }
+
+ inline BOOL CWnd::EnableWindow(BOOL bEnable /*= TRUE*/) const
+ // The EnableWindow function enables or disables mouse and
+ // keyboard input to the window.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ::EnableWindow(m_hWnd, bEnable);
+ }
+
+ inline BOOL CWnd::EndPaint(PAINTSTRUCT& ps) const
+ // The EndPaint function marks the end of painting in the specified window. This function is required for
+ // each call to the BeginPaint function, but only after painting is complete.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ::EndPaint(m_hWnd, &ps);
+ }
+
+ inline CWnd* CWnd::GetActiveWindow() const
+ // The GetActiveWindow function retrieves a pointer to the active window attached to the calling
+ // thread's message queue.
+ {
+ return FromHandle( ::GetActiveWindow() );
+ }
+
+ inline CWnd* CWnd::GetCapture() const
+ // The GetCapture function retrieves a pointer to the window (if any) that has captured the mouse.
+ {
+ return FromHandle( ::GetCapture() );
+ }
+
+ inline ULONG_PTR CWnd::GetClassLongPtr(int nIndex) const
+ // The GetClassLongPtr function retrieves the specified value from the
+ // WNDCLASSEX structure associated with the window.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ::GetClassLongPtr(m_hWnd, nIndex);
+ }
+
+ inline CRect CWnd::GetClientRect() const
+ // The GetClientRect function retrieves the coordinates of a window's client area.
+ // The client coordinates specify the upper-left and lower-right corners of the
+ // client area. Because client coordinates are relative to the upper-left corner
+ // of a window's client area, the coordinates of the upper-left corner are (0,0).
+ {
+ assert(::IsWindow(m_hWnd));
+ CRect rc;
+ ::GetClientRect(m_hWnd, &rc);
+ return rc;
+ }
+
+ inline CDC* CWnd::GetDC() const
+ // The GetDC function retrieves a handle to a display device context (DC) for the
+ // client area of the window.
+ {
+ assert(::IsWindow(m_hWnd));
+ return CDC::AddTempHDC(::GetDC(m_hWnd), m_hWnd);
+ }
+
+ inline CDC* CWnd::GetDCEx(HRGN hrgnClip, DWORD flags) const
+ // The GetDCEx function retrieves a handle to a display device context (DC) for the
+ // client area or entire area of a window
+ {
+ assert(::IsWindow(m_hWnd));
+ return CDC::AddTempHDC(::GetDCEx(m_hWnd, hrgnClip, flags), m_hWnd);
+ }
+
+ inline CWnd* CWnd::GetDesktopWindow() const
+ // The GetDesktopWindow function retrieves a pointer to the desktop window.
+ {
+ return FromHandle( ::GetDesktopWindow() );
+ }
+
+ inline CWnd* CWnd::GetDlgItem(int nIDDlgItem) const
+ // The GetDlgItem function retrieves a handle to a control in the dialog box.
+ {
+ assert(::IsWindow(m_hWnd));
+ return FromHandle( ::GetDlgItem(m_hWnd, nIDDlgItem) );
+ }
+
+ inline UINT CWnd::GetDlgItemInt(int nIDDlgItem, BOOL* lpTranslated, BOOL bSigned) const
+ // The GetDlgItemInt function translates the text of a specified control in a dialog box into an integer value.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ::GetDlgItemInt(m_hWnd, nIDDlgItem, lpTranslated, bSigned);
+ }
+
+ inline CWnd* CWnd::GetFocus() const
+ // The GetFocus function retrieves a pointer to the window that has the keyboard focus, if the window
+ // is attached to the calling thread's message queue.
+ {
+ return FromHandle( ::GetFocus() );
+ }
+
+ inline CFont* CWnd::GetFont() const
+ // Retrieves the font with which the window is currently drawing its text.
+ {
+ assert(::IsWindow(m_hWnd));
+ return FromHandle((HFONT)SendMessage(WM_GETFONT, 0, 0));
+ }
+
+ inline HICON CWnd::GetIcon(BOOL bBigIcon) const
+ // Retrieves a handle to the large or small icon associated with a window.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (HICON)SendMessage(WM_GETICON, (WPARAM)bBigIcon, 0);
+ }
+
+ inline CWnd* CWnd::GetNextDlgGroupItem(CWnd* pCtl, BOOL bPrevious) const
+ // The GetNextDlgGroupItem function retrieves a pointer to the first control in a group of controls that
+ // precedes (or follows) the specified control in a dialog box.
+ {
+ assert(::IsWindow(m_hWnd));
+ assert(pCtl);
+ return FromHandle(::GetNextDlgGroupItem(m_hWnd, pCtl->GetHwnd(), bPrevious));
+ }
+
+ inline CWnd* CWnd::GetNextDlgTabItem(CWnd* pCtl, BOOL bPrevious) const
+ // The GetNextDlgTabItem function retrieves a pointer to the first control that has the WS_TABSTOP style
+ // that precedes (or follows) the specified control.
+ {
+ assert(::IsWindow(m_hWnd));
+ assert(pCtl);
+ return FromHandle(::GetNextDlgTabItem(m_hWnd, pCtl->GetHwnd(), bPrevious));
+ }
+
+ inline CWnd* CWnd::GetParent() const
+ // The GetParent function retrieves a pointer to the specified window's parent or owner.
+ {
+ assert(::IsWindow(m_hWnd));
+ return FromHandle( ::GetParent(m_hWnd) );
+ }
+
+ inline LONG_PTR CWnd::GetWindowLongPtr(int nIndex) const
+ // The GetWindowLongPtr function retrieves information about the window.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ::GetWindowLongPtr(m_hWnd, nIndex);
+ }
+
+ inline BOOL CWnd::GetScrollInfo(int fnBar, SCROLLINFO& si) const
+ // The GetScrollInfo function retrieves the parameters of a scroll bar, including
+ // the minimum and maximum scrolling positions, the page size, and the position
+ // of the scroll box (thumb).
+ {
+ assert(::IsWindow(m_hWnd));
+ return ::GetScrollInfo(m_hWnd, fnBar, &si);
+ }
+
+ inline CRect CWnd::GetUpdateRect(BOOL bErase) const
+ // The GetUpdateRect function retrieves the coordinates of the smallest rectangle that completely
+ // encloses the update region of the specified window.
+ {
+ assert(::IsWindow(m_hWnd));
+ CRect rc;
+ ::GetUpdateRect(m_hWnd, &rc, bErase);
+ return rc;
+ }
+
+ inline int CWnd::GetUpdateRgn(CRgn* pRgn, BOOL bErase) const
+ // The GetUpdateRgn function retrieves the update region of a window by copying it into the specified region.
+ {
+ assert(::IsWindow(m_hWnd));
+ assert(pRgn);
+ HRGN hRgn = (HRGN)pRgn->GetHandle();
+ return ::GetUpdateRgn(m_hWnd, hRgn, bErase);
+ }
+
+ inline CWnd* CWnd::GetWindow(UINT uCmd) const
+ // The GetWindow function retrieves a pointer to a window that has the specified
+ // relationship (Z-Order or owner) to the specified window.
+ // Possible uCmd values: GW_CHILD, GW_ENABLEDPOPUP, GW_HWNDFIRST, GW_HWNDLAST,
+ // GW_HWNDNEXT, GW_HWNDPREV, GW_OWNER
+ {
+ assert(::IsWindow(m_hWnd));
+ return FromHandle( ::GetWindow(m_hWnd, uCmd) );
+ }
+
+ inline CDC* CWnd::GetWindowDC() const
+ // The GetWindowDC function retrieves the device context (DC) for the entire
+ // window, including title bar, menus, and scroll bars.
+ {
+ assert(::IsWindow(m_hWnd));
+ return CDC::AddTempHDC(::GetWindowDC(m_hWnd), m_hWnd);
+ }
+
+ inline CRect CWnd::GetWindowRect() const
+ // retrieves the dimensions of the bounding rectangle of the window.
+ // The dimensions are given in screen coordinates that are relative to the
+ // upper-left corner of the screen.
+ {
+ assert(::IsWindow(m_hWnd));
+ CRect rc;
+ ::GetWindowRect(m_hWnd, &rc);
+ return rc;
+ }
+
+ inline int CWnd::GetWindowTextLength() const
+ // The GetWindowTextLength function retrieves the length, in characters, of the specified window's
+ // title bar text (if the window has a title bar).
+ {
+ assert(::IsWindow(m_hWnd));
+ return ::GetWindowTextLength(m_hWnd);
+ }
+
+ inline void CWnd::Invalidate(BOOL bErase /*= TRUE*/) const
+ // The Invalidate function adds the entire client area the window's update region.
+ // The update region represents the portion of the window's client area that must be redrawn.
+ {
+ assert(::IsWindow(m_hWnd));
+ ::InvalidateRect(m_hWnd, NULL, bErase);
+ }
+
+ inline BOOL CWnd::InvalidateRect(LPCRECT lpRect, BOOL bErase /*= TRUE*/) const
+ // The InvalidateRect function adds a rectangle to the window's update region.
+ // The update region represents the portion of the window's client area that must be redrawn.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ::InvalidateRect(m_hWnd, lpRect, bErase);
+ }
+
+ inline BOOL CWnd::InvalidateRgn(CRgn* pRgn, BOOL bErase /*= TRUE*/) const
+ // The InvalidateRgn function invalidates the client area within the specified region
+ // by adding it to the current update region of a window. The invalidated region,
+ // along with all other areas in the update region, is marked for painting when the
+ // next WM_PAINT message occurs.
+ {
+ assert(::IsWindow(m_hWnd));
+ HRGN hRgn = pRgn? (HRGN)pRgn->GetHandle() : NULL;
+ return ::InvalidateRgn(m_hWnd, hRgn, bErase);
+ }
+
+ inline BOOL CWnd::IsChild(CWnd* pChild) const
+ // The IsChild function tests whether a window is a child window or descendant window
+ // of a parent window's CWnd.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ::IsChild(m_hWnd, pChild->GetHwnd());
+ }
+
+ inline BOOL CWnd::IsDialogMessage(LPMSG lpMsg) const
+ // The IsDialogMessage function determines whether a message is intended for the specified dialog box and,
+ // if it is, processes the message.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ::IsDialogMessage(m_hWnd, lpMsg);
+ }
+
+ inline UINT CWnd::IsDlgButtonChecked(int nIDButton) const
+ // The IsDlgButtonChecked function determines whether a button control has a check mark next to it
+ // or whether a three-state button control is grayed, checked, or neither.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ::IsDlgButtonChecked(m_hWnd, nIDButton);
+ }
+
+ inline BOOL CWnd::IsWindowEnabled() const
+ // The IsWindowEnabled function determines whether the window is enabled
+ // for mouse and keyboard input.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ::IsWindowEnabled(m_hWnd);
+ }
+
+ inline BOOL CWnd::IsWindowVisible() const
+ // The IsWindowVisible function retrieves the visibility state of the window.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ::IsWindowVisible(m_hWnd);
+ }
+
+ inline BOOL CWnd::IsWindow() const
+ // The IsWindow function determines whether the window exists.
+ {
+ return ::IsWindow(m_hWnd);
+ }
+
+ inline void CWnd::MapWindowPoints(CWnd* pWndTo, POINT& pt) const
+ // The MapWindowPoints function converts (maps) a set of points from a coordinate space relative to one
+ // window to a coordinate space relative to another window.
+ {
+ assert (m_hWnd);
+ if(pWndTo)
+ {
+ assert (pWndTo->GetHwnd());
+ ::MapWindowPoints(m_hWnd, pWndTo->GetHwnd(), &pt, 1);
+ }
+ else
+ ::MapWindowPoints(m_hWnd, NULL, &pt, 1);
+ }
+
+ inline void CWnd::MapWindowPoints(CWnd* pWndTo, RECT& rc) const
+ // The MapWindowPoints function converts (maps) a set of points from a coordinate space relative to one
+ // window to a coordinate space relative to another window.
+ {
+ assert (m_hWnd);
+ if(pWndTo)
+ {
+ assert (pWndTo->GetHwnd());
+ ::MapWindowPoints(m_hWnd, pWndTo->GetHwnd(), (LPPOINT)&rc, 2);
+ }
+ else
+ ::MapWindowPoints(m_hWnd, NULL, (LPPOINT)&rc, 2);
+ }
+
+ inline void CWnd::MapWindowPoints(CWnd* pWndTo, LPPOINT ptArray, UINT nCount) const
+ // The MapWindowPoints function converts (maps) a set of points from a coordinate space relative to one
+ // window to a coordinate space relative to another window.
+ {
+ assert (m_hWnd);
+ if (pWndTo)
+ {
+ assert (pWndTo->GetHwnd());
+ ::MapWindowPoints(m_hWnd, pWndTo->GetHwnd(), (LPPOINT)ptArray, nCount);
+ }
+ else
+ ::MapWindowPoints(m_hWnd, NULL, (LPPOINT)ptArray, nCount);
+ }
+
+ inline int CWnd::MessageBox(LPCTSTR lpText, LPCTSTR lpCaption, UINT uType) const
+ // The MessageBox function creates, displays, and operates a message box.
+ // Possible combinations of uType values include: MB_OK, MB_HELP, MB_OKCANCEL, MB_RETRYCANCEL,
+ // MB_YESNO, MB_YESNOCANCEL, MB_ICONEXCLAMATION, MB_ICONWARNING, MB_ICONERROR (+ many others).
+ {
+ assert(::IsWindow(m_hWnd));
+ return ::MessageBox(m_hWnd, lpText, lpCaption, uType);
+ }
+
+ inline BOOL CWnd::MoveWindow(int x, int y, int nWidth, int nHeight, BOOL bRepaint /* = TRUE*/) const
+ // The MoveWindow function changes the position and dimensions of the window.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ::MoveWindow(m_hWnd, x, y, nWidth, nHeight, bRepaint = TRUE);
+ }
+
+ inline BOOL CWnd::MoveWindow(const RECT& rc, BOOL bRepaint /* = TRUE*/) const
+ // The MoveWindow function changes the position and dimensions of the window.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ::MoveWindow(m_hWnd, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, bRepaint);
+ }
+
+ inline BOOL CWnd::PostMessage(UINT uMsg, WPARAM wParam /*= 0L*/, LPARAM lParam /*= 0L*/) const
+ // The PostMessage function places (posts) a message in the message queue
+ // associated with the thread that created the window and returns without
+ // waiting for the thread to process the message.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ::PostMessage(m_hWnd, uMsg, wParam, lParam);
+ }
+
+ inline BOOL CWnd::PostMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) const
+ // Required by by some macros
+ {
+ assert(::IsWindow(m_hWnd));
+ return ::PostMessage(hWnd, uMsg, wParam, lParam);
+ }
+
+ inline BOOL CWnd::RedrawWindow(LPCRECT lpRectUpdate, CRgn* pRgn, UINT flags) const
+ // The RedrawWindow function updates the specified rectangle or region in a window's client area.
+ {
+ assert(::IsWindow(m_hWnd));
+ HRGN hRgn = pRgn? (HRGN)pRgn->GetHandle() : NULL;
+ return ::RedrawWindow(m_hWnd, lpRectUpdate, hRgn, flags);
+ }
+
+ inline int CWnd::ReleaseDC(CDC* pDC) const
+ // The ReleaseDC function releases a device context (DC), freeing it for use
+ // by other applications.
+ {
+ assert(::IsWindow(m_hWnd));
+ assert(pDC);
+ return ::ReleaseDC(m_hWnd, pDC->GetHDC());
+ }
+
+ inline BOOL CWnd::ScreenToClient(POINT& Point) const
+ // The ScreenToClient function converts the screen coordinates of a specified point on the screen to client-area coordinates.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ::ScreenToClient(m_hWnd, &Point);
+ }
+
+ inline BOOL CWnd::ScreenToClient(RECT& rc) const
+ // The ScreenToClient function converts the screen coordinates of a specified RECT on the screen to client-area coordinates.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (BOOL)::MapWindowPoints(NULL, m_hWnd, (LPPOINT)&rc, 2);
+ }
+
+ inline LRESULT CWnd::SendDlgItemMessage(int nIDDlgItem, UINT Msg, WPARAM wParam, LPARAM lParam) const
+ // The SendDlgItemMessage function sends a message to the specified control in a dialog box.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ::SendDlgItemMessage(m_hWnd, nIDDlgItem, Msg, wParam, lParam);
+ }
+
+ inline LRESULT CWnd::SendMessage(UINT uMsg, WPARAM wParam /*= 0L*/, LPARAM lParam /*= 0L*/) const
+ // The SendMessage function sends the specified message to a window or windows.
+ // It calls the window procedure for the window and does not return until the
+ // window procedure has processed the message.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ::SendMessage(m_hWnd, uMsg, wParam, lParam);
+ }
+
+ inline LRESULT CWnd::SendMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) const
+ // Required by by some macros
+ {
+ assert(::IsWindow(m_hWnd));
+ return ::SendMessage(hWnd, uMsg, wParam, lParam);
+ }
+
+ inline BOOL CWnd::SendNotifyMessage(UINT Msg, WPARAM wParam, LPARAM lParam) const
+ // The SendNotifyMessage function sends the specified message to a window or windows. If the window was created by the
+ // calling thread, SendNotifyMessage calls the window procedure for the window and does not return until the window procedure
+ // has processed the message. If the window was created by a different thread, SendNotifyMessage passes the message to the
+ // window procedure and returns immediately; it does not wait for the window procedure to finish processing the message.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ::SendNotifyMessage(m_hWnd, Msg, wParam, lParam);
+ }
+
+ inline CWnd* CWnd::SetActiveWindow() const
+ // The SetActiveWindow function activates the window, but
+ // not if the application is in the background.
+ {
+ assert(::IsWindow(m_hWnd));
+ return FromHandle( ::SetActiveWindow(m_hWnd) );
+ }
+
+ inline CWnd* CWnd::SetCapture() const
+ // The SetCapture function sets the mouse capture to the window.
+ // SetCapture captures mouse input either when the mouse is over the capturing
+ // window, or when the mouse button was pressed while the mouse was over the
+ // capturing window and the button is still down.
+ {
+ assert(::IsWindow(m_hWnd));
+ return FromHandle( ::SetCapture(m_hWnd) );
+ }
+
+ inline ULONG_PTR CWnd::SetClassLongPtr(int nIndex, LONG_PTR dwNewLong) const
+ // The SetClassLongPtr function replaces the specified value at the specified offset in the
+ // extra class memory or the WNDCLASSEX structure for the class to which the window belongs.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ::SetClassLongPtr(m_hWnd, nIndex, dwNewLong);
+ }
+
+ inline CWnd* CWnd::SetFocus() const
+ // The SetFocus function sets the keyboard focus to the window.
+ {
+ assert(::IsWindow(m_hWnd));
+ return FromHandle( ::SetFocus(m_hWnd) );
+ }
+
+ inline void CWnd::SetFont(CFont* pFont, BOOL bRedraw /* = TRUE*/) const
+ // Specifies the font that the window will use when drawing text.
+ {
+ assert(::IsWindow(m_hWnd));
+ assert(pFont);
+ SendMessage(WM_SETFONT, (WPARAM)pFont->GetHandle(), (LPARAM)bRedraw);
+ }
+
+ inline HICON CWnd::SetIcon(HICON hIcon, BOOL bBigIcon) const
+ // Associates a new large or small icon with a window.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (HICON)SendMessage(WM_SETICON, (WPARAM)bBigIcon, (LPARAM)hIcon);
+ }
+
+ inline BOOL CWnd::SetForegroundWindow() const
+ // The SetForegroundWindow function puts the thread that created the window into the
+ // foreground and activates the window.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ::SetForegroundWindow(m_hWnd);
+ }
+
+ inline CWnd* CWnd::SetParent(CWnd* pWndParent) const
+ // The SetParent function changes the parent window of the child window.
+ {
+ assert(::IsWindow(m_hWnd));
+ if (pWndParent)
+ {
+ HWND hParent = pWndParent->GetHwnd();
+ return FromHandle(::SetParent(m_hWnd, hParent));
+ }
+ else
+ return FromHandle(::SetParent(m_hWnd, 0));
+ }
+
+ inline BOOL CWnd::SetRedraw(BOOL bRedraw /*= TRUE*/) const
+ // This function allows changes in that window to be redrawn or prevents changes
+ // in that window from being redrawn.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (BOOL)::SendMessage(m_hWnd, WM_SETREDRAW, (WPARAM)bRedraw, 0L);
+ }
+
+ inline LONG_PTR CWnd::SetWindowLongPtr(int nIndex, LONG_PTR dwNewLong) const
+ // The SetWindowLongPtr function changes an attribute of the window.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ::SetWindowLongPtr(m_hWnd, nIndex, dwNewLong);
+ }
+
+ inline BOOL CWnd::SetWindowPos(HWND hWndInsertAfter, int x, int y, int cx, int cy, UINT uFlags) const
+ // The SetWindowPos function changes the size, position, and Z order of a child, pop-up,
+ // or top-level window. The hWndInsertAfter can be a HWND or one of:
+ // HWND_BOTTOM, HWND_NOTOPMOST, HWND_TOP, HWND_TOPMOST
+ {
+ assert(::IsWindow(m_hWnd));
+ return ::SetWindowPos(m_hWnd, hWndInsertAfter, x, y, cx, cy, uFlags);
+ }
+
+ inline BOOL CWnd::SetWindowPos(HWND hWndInsertAfter, const RECT& rc, UINT uFlags) const
+ // The SetWindowPos function changes the size, position, and Z order of a child, pop-up,
+ // or top-level window. The hWndInsertAfter can be a HWND or one of:
+ // HWND_BOTTOM, HWND_NOTOPMOST, HWND_TOP, HWND_TOPMOST
+ {
+ assert(::IsWindow(m_hWnd));
+ return ::SetWindowPos(m_hWnd, hWndInsertAfter, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, uFlags);
+ }
+
+ inline int CWnd::SetWindowRgn(CRgn* pRgn, BOOL bRedraw /*= TRUE*/) const
+ // The SetWindowRgn function sets the window region of the window.
+ // The window region determines the area within the window where the system permits drawing.
+ {
+ assert(::IsWindow(m_hWnd));
+ HRGN hRgn = pRgn? (HRGN)pRgn->GetHandle() : NULL;
+ int iResult = ::SetWindowRgn(m_hWnd, hRgn, bRedraw);
+ if (iResult && pRgn)
+ pRgn->Detach(); // The system owns the region now
+ return iResult;
+ }
+
+ inline BOOL CWnd::SetDlgItemInt(int nIDDlgItem, UINT uValue, BOOL bSigned) const
+ // The SetDlgItemInt function sets the text of a control in a dialog box to the string representation of a specified integer value.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ::SetDlgItemInt(m_hWnd, nIDDlgItem, uValue, bSigned);
+ }
+
+ inline BOOL CWnd::SetDlgItemText(int nIDDlgItem, LPCTSTR lpString) const
+ // The SetDlgItemText function sets the title or text of a control in a dialog box.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ::SetDlgItemText(m_hWnd, nIDDlgItem, lpString);
+ }
+
+ inline UINT_PTR CWnd::SetTimer(UINT_PTR nIDEvent, UINT uElapse, TIMERPROC lpTimerFunc) const
+ // Creates a timer with the specified time-out value.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ::SetTimer(m_hWnd, nIDEvent, uElapse, lpTimerFunc);
+ }
+
+ inline BOOL CWnd::SetWindowText(LPCTSTR lpString) const
+ // The SetWindowText function changes the text of the window's title bar (if it has one).
+ {
+ assert(::IsWindow(m_hWnd));
+ return ::SetWindowText(m_hWnd, lpString);
+ }
+
+ inline HRESULT CWnd::SetWindowTheme(LPCWSTR pszSubAppName, LPCWSTR pszSubIdList) const
+ // Set the XP Theme for a window.
+ // Exampes:
+ // SetWindowTheme(NULL, NULL); // Reverts the window's XP theme back to default
+ // SetWindowTheme(L" ", L" "); // Disables XP theme for the window
+ {
+ HRESULT hr = E_NOTIMPL;
+
+#ifndef _WIN32_WCE
+
+ HMODULE hMod = ::LoadLibrary(_T("uxtheme.dll"));
+ if(hMod)
+ {
+ typedef HRESULT (__stdcall *PFNSETWINDOWTHEME)(HWND hWnd, LPCWSTR pszSubAppName, LPCWSTR pszSubIdList);
+ PFNSETWINDOWTHEME pfn = (PFNSETWINDOWTHEME)GetProcAddress(hMod, "SetWindowTheme");
+
+ hr = (*pfn)(m_hWnd, pszSubAppName, pszSubIdList);
+
+ ::FreeLibrary(hMod);
+ }
+
+#endif
+
+ return hr;
+ }
+
+ inline BOOL CWnd::ShowWindow(int nCmdShow /*= SW_SHOWNORMAL*/) const
+ // The ShowWindow function sets the window's show state.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ::ShowWindow(m_hWnd, nCmdShow);
+ }
+
+ inline BOOL CWnd::UpdateWindow() const
+ // The UpdateWindow function updates the client area of the window by sending a
+ // WM_PAINT message to the window if the window's update region is not empty.
+ // If the update region is empty, no message is sent.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ::UpdateWindow(m_hWnd);
+ }
+
+ inline BOOL CWnd::ValidateRect(LPCRECT prc) const
+ // The ValidateRect function validates the client area within a rectangle by
+ // removing the rectangle from the update region of the window.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ::ValidateRect(m_hWnd, prc);
+ }
+
+ inline BOOL CWnd::ValidateRgn(CRgn* pRgn) const
+ // The ValidateRgn function validates the client area within a region by
+ // removing the region from the current update region of the window.
+ {
+ assert(::IsWindow(m_hWnd));
+ HRGN hRgn = pRgn? (HRGN)pRgn->GetHandle() : NULL;
+ return ::ValidateRgn(m_hWnd, hRgn);
+ }
+
+ inline CWnd* CWnd::WindowFromPoint(POINT pt)
+ // Retrieves the window that contains the specified point (in screen coodinates).
+ {
+ return FromHandle(::WindowFromPoint(pt));
+ }
+
+ //
+ // These functions aren't supported on WinCE
+ //
+ #ifndef _WIN32_WCE
+ inline BOOL CWnd::CloseWindow() const
+ // The CloseWindow function minimizes (but does not destroy) the window.
+ // To destroy a window, an application can use the Destroy function.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ::CloseWindow(m_hWnd);
+ }
+
+ inline int CWnd::DlgDirList(LPTSTR lpPathSpec, int nIDListBox, int nIDStaticPath, UINT uFileType) const
+ // The DlgDirList function replaces the contents of a list box with the names of the subdirectories and files
+ // in a specified directory. You can filter the list of names by specifying a set of file attributes.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ::DlgDirList(m_hWnd, lpPathSpec, nIDListBox, nIDStaticPath, uFileType);
+ }
+
+ inline int CWnd::DlgDirListComboBox(LPTSTR lpPathSpec, int nIDComboBox, int nIDStaticPath, UINT uFiletype) const
+ // The DlgDirListComboBox function replaces the contents of a combo box with the names of the subdirectories
+ // and files in a specified directory. You can filter the list of names by specifying a set of file attributes.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ::DlgDirListComboBox(m_hWnd, lpPathSpec, nIDComboBox, nIDStaticPath, uFiletype);
+ }
+
+ inline BOOL CWnd::DlgDirSelectEx(LPTSTR lpString, int nCount, int nIDListBox) const
+ // The DlgDirSelectEx function retrieves the current selection from a single-selection list box. It assumes that the list box
+ // has been filled by the DlgDirList function and that the selection is a drive letter, filename, or directory name.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ::DlgDirSelectEx(m_hWnd, lpString, nCount, nIDListBox);
+ }
+
+ inline BOOL CWnd::DlgDirSelectComboBoxEx(LPTSTR lpString, int nCount, int nIDComboBox) const
+ // The DlgDirSelectComboBoxEx function retrieves the current selection from a combo box filled by using the
+ // DlgDirListComboBox function. The selection is interpreted as a drive letter, a file, or a directory name.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ::DlgDirSelectComboBoxEx(m_hWnd, lpString, nCount, nIDComboBox);
+ }
+
+ #ifndef WIN32_LEAN_AND_MEAN
+ inline void CWnd::DragAcceptFiles(BOOL fAccept) const
+ // Registers whether a window accepts dropped files.
+ {
+ assert(::IsWindow(m_hWnd));
+ ::DragAcceptFiles(m_hWnd, fAccept);
+ }
+ #endif
+
+ inline BOOL CWnd::DrawAnimatedRects(int idAni, RECT& rcFrom, RECT& rcTo) const
+ // The DrawAnimatedRects function draws a wire-frame rectangle and animates it to indicate the opening of
+ // an icon or the minimizing or maximizing of a window.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ::DrawAnimatedRects(m_hWnd, idAni, &rcFrom, &rcTo);
+ }
+
+ inline BOOL CWnd::DrawCaption(CDC* pDC, RECT& rc, UINT uFlags) const
+ // The DrawCaption function draws a window caption.
+ {
+ assert(::IsWindow(m_hWnd));
+ assert(pDC);
+ return ::DrawCaption(m_hWnd, pDC->GetHDC(), &rc, uFlags);
+ }
+
+ inline BOOL CWnd::EnableScrollBar(UINT uSBflags, UINT uArrows) const
+ // The EnableScrollBar function enables or disables one or both scroll bar arrows.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ::EnableScrollBar(m_hWnd, uSBflags, uArrows);
+ }
+
+ inline CWnd* CWnd::GetLastActivePopup() const
+ // The GetLastActivePopup function determines which pop-up window owned by the specified window was most recently active.
+ {
+ assert(::IsWindow(m_hWnd));
+ return FromHandle( ::GetLastActivePopup(m_hWnd) );
+ }
+
+ inline CMenu* CWnd::GetMenu() const
+ // The GetMenu function retrieves a handle to the menu assigned to the window.
+ {
+ assert(::IsWindow(m_hWnd));
+ return FromHandle(::GetMenu(m_hWnd));
+ }
+
+ inline int CWnd::GetScrollPos(int nBar) const
+ // The GetScrollPos function retrieves the current position of the scroll box
+ // (thumb) in the specified scroll bar.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ::GetScrollPos(m_hWnd, nBar);
+ }
+
+ inline BOOL CWnd::GetScrollRange(int nBar, int& MinPos, int& MaxPos) const
+ // The GetScrollRange function retrieves the current minimum and maximum scroll box
+ // (thumb) positions for the specified scroll bar.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ::GetScrollRange(m_hWnd, nBar, &MinPos, &MaxPos );
+ }
+
+ inline CMenu* CWnd::GetSystemMenu(BOOL bRevert) const
+ // The GetSystemMenu function allows the application to access the window menu (also known as the system menu
+ // or the control menu) for copying and modifying.
+ {
+ assert(::IsWindow(m_hWnd));
+ return FromHandle(::GetSystemMenu(m_hWnd, bRevert));
+ }
+
+ inline CWnd* CWnd::GetTopWindow() const
+ // The GetTopWindow function examines the Z order of the child windows associated with the parent window and
+ // retrieves a handle to the child window at the top of the Z order.
+ {
+ assert(::IsWindow(m_hWnd));
+ return FromHandle( ::GetTopWindow(m_hWnd) );
+ }
+
+ inline BOOL CWnd::GetWindowPlacement(WINDOWPLACEMENT& wndpl) const
+ // The GetWindowPlacement function retrieves the show state and the restored,
+ // minimized, and maximized positions of the window.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ::GetWindowPlacement(m_hWnd, &wndpl);
+ }
+
+ inline BOOL CWnd::HiliteMenuItem(CMenu* pMenu, UINT uItemHilite, UINT uHilite) const
+ // The HiliteMenuItem function highlights or removes the highlighting from an item in a menu bar.
+ {
+ assert(::IsWindow(m_hWnd));
+ assert(pMenu);
+ return ::HiliteMenuItem(m_hWnd, pMenu->GetHandle(), uItemHilite, uHilite);
+ }
+
+ inline BOOL CWnd::IsIconic() const
+ // The IsIconic function determines whether the window is minimized (iconic).
+ {
+ assert(::IsWindow(m_hWnd));
+ return ::IsIconic(m_hWnd);
+ }
+
+ inline BOOL CWnd::IsZoomed() const
+ // The IsZoomed function determines whether the window is maximized.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ::IsZoomed(m_hWnd);
+ }
+
+ inline BOOL CWnd::KillTimer(UINT_PTR uIDEvent) const
+ // Destroys the specified timer.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ::KillTimer(m_hWnd, uIDEvent);
+ }
+
+ inline BOOL CWnd::LockWindowUpdate() const
+ // Disables drawing in the window. Only one window can be locked at a time.
+ // Use UnLockWindowUpdate to re-enable drawing in the window
+ {
+ assert(::IsWindow(m_hWnd));
+ return ::LockWindowUpdate(m_hWnd);
+ }
+
+ inline BOOL CWnd::OpenIcon() const
+ // The OpenIcon function restores a minimized (iconic) window to its previous size and position.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ::OpenIcon(m_hWnd);
+ }
+
+ inline void CWnd::Print(CDC* pDC, DWORD dwFlags) const
+ // Requests that the window draw itself in the specified device context, most commonly in a printer device context.
+ {
+ assert(::IsWindow(m_hWnd));
+ assert(pDC);
+ SendMessage(m_hWnd, WM_PRINT, (WPARAM)pDC, (LPARAM)dwFlags);
+ }
+
+ inline BOOL CWnd::ScrollWindow(int XAmount, int YAmount, LPCRECT lprcScroll, LPCRECT lprcClip) const
+ // The ScrollWindow function scrolls the contents of the specified window's client area.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ::ScrollWindow(m_hWnd, XAmount, YAmount, lprcScroll, lprcClip);
+ }
+
+ inline int CWnd::ScrollWindowEx(int dx, int dy, LPCRECT lprcScroll, LPCRECT lprcClip, CRgn* prgnUpdate, LPRECT lprcUpdate, UINT flags) const
+ // The ScrollWindow function scrolls the contents of the window's client area.
+ {
+ assert(::IsWindow(m_hWnd));
+ HRGN hrgnUpdate = prgnUpdate? (HRGN)prgnUpdate->GetHandle() : NULL;
+ return ::ScrollWindowEx(m_hWnd, dx, dy, lprcScroll, lprcClip, hrgnUpdate, lprcUpdate, flags);
+ }
+
+ inline BOOL CWnd::SetMenu(CMenu* pMenu) const
+ // The SetMenu function assigns a menu to the specified window.
+ // A hMenu of NULL removes the menu.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ::SetMenu(m_hWnd, pMenu? pMenu->GetHandle() : NULL);
+ }
+
+ inline int CWnd::SetScrollInfo(int fnBar, const SCROLLINFO& si, BOOL fRedraw) const
+ // The SetScrollInfo function sets the parameters of a scroll bar, including
+ // the minimum and maximum scrolling positions, the page size, and the
+ // position of the scroll box (thumb).
+ {
+ assert(::IsWindow(m_hWnd));
+ return ::SetScrollInfo(m_hWnd, fnBar, &si, fRedraw);
+ }
+
+ inline int CWnd::SetScrollPos(int nBar, int nPos, BOOL bRedraw) const
+ // The SetScrollPos function sets the position of the scroll box (thumb) in
+ // the specified scroll bar.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ::SetScrollPos(m_hWnd, nBar, nPos, bRedraw);
+ }
+
+ inline BOOL CWnd::SetScrollRange(int nBar, int nMinPos, int nMaxPos, BOOL bRedraw) const
+ // The SetScrollRange function sets the minimum and maximum scroll box positions for the scroll bar.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ::SetScrollRange(m_hWnd, nBar, nMinPos, nMaxPos, bRedraw);
+ }
+
+ inline BOOL CWnd::SetWindowPlacement(const WINDOWPLACEMENT& wndpl) const
+ // The SetWindowPlacement function sets the show state and the restored, minimized,
+ // and maximized positions of the window.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ::SetWindowPlacement(m_hWnd, &wndpl);
+ }
+
+ inline BOOL CWnd::ShowOwnedPopups(BOOL fShow) const
+ // The ShowOwnedPopups function shows or hides all pop-up windows owned by the specified window.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ::ShowOwnedPopups(m_hWnd, fShow);
+ }
+
+ inline BOOL CWnd::ShowScrollBar(int nBar, BOOL bShow) const
+ // The ShowScrollBar function shows or hides the specified scroll bar.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ::ShowScrollBar(m_hWnd, nBar, bShow);
+ }
+
+ inline BOOL CWnd::ShowWindowAsync(int nCmdShow) const
+ // The ShowWindowAsync function sets the show state of a window created by a different thread.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ::ShowWindowAsync(m_hWnd, nCmdShow);
+ }
+
+ inline BOOL CWnd::UnLockWindowUpdate() const
+ // Enables drawing in the window. Only one window can be locked at a time.
+ // Use LockWindowUpdate to disable drawing in the window
+ {
+ assert(::IsWindow(m_hWnd));
+ return ::LockWindowUpdate(0);
+ }
+
+ inline CWnd* CWnd::WindowFromDC(CDC* pDC) const
+ // The WindowFromDC function returns a handle to the window associated with the specified display device context (DC).
+ {
+ assert(pDC);
+ return FromHandle( ::WindowFromDC(pDC->GetHDC()) );
+ }
+
+ #endif
+
+}; // namespace Win32xx
+
+
+#endif // _WIN32XX_WINCORE_H_
+
diff --git a/mmc_updater/depends/win32cpp/winutils.h b/mmc_updater/depends/win32cpp/winutils.h
new file mode 100644
index 00000000..94ba2d80
--- /dev/null
+++ b/mmc_updater/depends/win32cpp/winutils.h
@@ -0,0 +1,649 @@
+// Win32++ Version 7.2
+// Released: 5th AUgust 2011
+//
+// David Nash
+// email: dnash@bigpond.net.au
+// url: https://sourceforge.net/projects/win32-framework
+//
+//
+// Copyright (c) 2005-2011 David Nash
+//
+// Permission is hereby granted, free of charge, to
+// any person obtaining a copy of this software and
+// associated documentation files (the "Software"),
+// to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify,
+// merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom
+// the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice
+// shall be included in all copies or substantial portions
+// of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
+// OR OTHER DEALINGS IN THE SOFTWARE.
+//
+////////////////////////////////////////////////////////
+
+#ifndef _WIN32XX_WINUTILS_H_
+#define _WIN32XX_WINUTILS_H_
+
+
+// define useful macros from WindowsX.h
+#ifndef GET_X_LPARAM
+ #define GET_X_LPARAM(lp) ((int)(short)LOWORD(lp))
+#endif
+#ifndef GET_Y_LPARAM
+ #define GET_Y_LPARAM(lp) ((int)(short)HIWORD(lp))
+#endif
+
+// Define our own MIN and MAX macros
+// this avoids inconsistencies with Dev-C++ and other compilers, and
+// avoids conflicts between typical min/max macros and std::min/std::max
+#define MAX(a,b) (((a) > (b)) ? (a) : (b))
+#define MIN(a,b) (((a) < (b)) ? (a) : (b))
+
+
+namespace Win32xx
+{
+ // Forward declarations
+ class CPoint;
+ class CRect;
+ CWinApp* GetApp();
+ void TRACE(LPCTSTR str);
+
+
+ /////////////////////////////////////////
+ // Definition of the CSize class
+ // This class can be used to replace the SIZE structure
+ class CSize : public SIZE
+ {
+ public:
+ CSize() { cx = 0; cy = 0; }
+ CSize(int CX, int CY) { cx = CX; cy = CY; }
+ CSize(SIZE sz) { cx = sz.cx; cy = sz.cy; }
+ CSize(POINT pt) { cx = pt.x; cy = pt.y; }
+ CSize(DWORD dw) { cx = (short)LOWORD(dw); cy = (short)HIWORD(dw); }
+ void SetSize(int CX, int CY) { cx = CX; cy = CY; }
+
+ // Operators
+ operator LPSIZE() { return this; }
+ BOOL operator == (SIZE sz) const { return (cx == sz.cx && cy == sz.cy); }
+ BOOL operator != (SIZE sz) const { return (cx != sz.cx || cy != sz.cy); }
+ void operator += (SIZE sz) { cx += sz.cx; cy += sz.cy; }
+ void operator -= (SIZE sz) { cx -= sz.cx; cy -= sz.cy; }
+
+ // Operators returning CSize
+ CSize operator - () const { return CSize (-cx, -cy); }
+ CSize operator + (SIZE sz) const { return CSize (cx + sz.cx, cy + sz.cy); }
+ CSize operator - (SIZE sz) const { return CSize (cx - sz.cx, cy - sz.cy); }
+
+ // Operators returning CPoint
+ CPoint operator + (POINT point) const;
+ CPoint operator - (POINT point) const;
+
+ // Operators returning CRect
+ CRect operator + (RECT rc) const;
+ CRect operator - (RECT rc) const;
+ };
+
+
+ /////////////////////////////////////////
+ // Definition of the CPoint class
+ // This class can be used to replace the POINT structure
+ class CPoint : public POINT
+ {
+ public:
+ CPoint() { x = 0; y = 0; }
+ CPoint(int X, int Y) { x = X; y = Y; }
+ CPoint(POINT pt) { x = pt.x ; y = pt.y; }
+ CPoint(POINTS pts) { x = pts.x; y = pts.y; }
+ CPoint(SIZE sz) { x = sz.cx; y = sz.cy; }
+ CPoint(DWORD dw) { x = (short) LOWORD(dw); y = (short) HIWORD(dw); }
+
+ void Offset(int dx, int dy) { x += dx; y += dy; }
+ void Offset(POINT pt) { x += pt.x; y += pt.y; }
+ void Offset(SIZE sz) { x += sz.cx; y += sz.cy; }
+ void SetPoint(int X, int Y) { x = X; y = Y; }
+
+ // Operators
+ operator LPPOINT() { return this; }
+ BOOL operator == (POINT pt) const { return ((x == pt.x) && (y == pt.y)); }
+ BOOL operator != (POINT pt) const { return ((x != pt.x) || (y != pt.y)); }
+ void operator += (SIZE sz) { x += sz.cx; y += sz.cy; }
+ void operator -= (SIZE sz) { x -= sz.cx; y -= sz.cy; }
+ void operator += (POINT pt) { x += pt.x; y += pt.y; }
+ void operator -= (POINT pt) { x -= pt.x; y -= pt.y; }
+
+ // Operators returning CPoint
+ CPoint operator - () const { return CPoint(-x, -y); }
+ CPoint operator + (SIZE sz) const { return CPoint(x + sz.cx, y + sz.cy); }
+ CPoint operator - (SIZE sz) const { return CPoint(x - sz.cx, y - sz.cy); }
+ CPoint operator + (POINT pt) const { return CPoint(x + pt.x, y + pt.y); }
+ CPoint operator - (POINT pt) const { return CPoint(x - pt.x, y - pt.y); }
+
+ // Operators returning CRect
+ CRect operator + (RECT rc) const;
+ CRect operator - (RECT rc) const;
+ };
+
+
+ /////////////////////////////////////////
+ // Definition of the CRect class
+ // This class can be used to replace the RECT structure.
+ class CRect : public RECT
+ {
+ public:
+ CRect() { left = top = right = bottom = 0; }
+ CRect(int l, int t, int r, int b) { left = l; top = t; right = r; bottom = b; }
+ CRect(RECT rc) { left = rc.left; top = rc.top; right = rc.right; bottom = rc.bottom; }
+ CRect(POINT pt, SIZE sz) { right = (left = pt.x) + sz.cx; bottom = (top = pt.y) + sz.cy; }
+ CRect(POINT topLeft, POINT bottomRight) { left = topLeft.x; top = topLeft.y; right = bottomRight.x; bottom = bottomRight.y; }
+
+ BOOL CopyRect(RECT rc) { return ::CopyRect(this, &rc); }
+ BOOL DeflateRect(int x, int y) { return ::InflateRect(this, -x, -y); }
+ BOOL DeflateRect(SIZE size) { return ::InflateRect(this, -size.cx, -size.cy); }
+ BOOL DeflateRect(RECT rc) { return ::InflateRect(this, rc.left - rc.right, rc.top - rc.bottom); }
+ BOOL DeflateRect(int l, int t, int r, int b){ return ::InflateRect(this, l - r, t - b); }
+ BOOL EqualRect(RECT rc) const { return ::EqualRect(&rc, this); }
+ BOOL InflateRect(int dx, int dy) { return ::InflateRect(this, dx, dy); }
+ BOOL InflateRect(SIZE sz) { return ::InflateRect(this, sz.cx, sz.cy); }
+ BOOL InflateRect(RECT rc) { return ::InflateRect(this, rc.right - rc.left, rc.bottom - rc.top); }
+ BOOL InflateRect(int l, int t, int r, int b){ return ::InflateRect(this, r - l, b - t); }
+ BOOL IntersectRect(RECT rc1, RECT rc2) { return ::IntersectRect(this, &rc1, &rc2); }
+ BOOL IsRectEmpty() const { return ::IsRectEmpty(this);}
+ BOOL IsRectNull() const { return (left == 0 && right == 0 && top == 0 && bottom == 0); }
+ CRect MulDiv(int nMult, int nDiv) const { return CRect ((left * nMult) / nDiv, (top * nMult) / nDiv,
+ (right * nMult) / nDiv, (bottom * nMult) / nDiv); }
+ void NormalizeRect() { int nTemp; if (left > right) { nTemp = left; left = right; right = nTemp; }
+ if (top > bottom) { nTemp = top; top = bottom; bottom = nTemp; } }
+ BOOL OffsetRect(int dx, int dy) { return ::OffsetRect(this, dx, dy); }
+ BOOL OffsetRect(POINT pt) { return ::OffsetRect(this, pt.x, pt.y); }
+ BOOL OffsetRect(SIZE size) { return ::OffsetRect(this, size.cx, size.cy); }
+ BOOL PtInRect(POINT pt) const { return ::PtInRect(this, pt); }
+ BOOL SetRect(int l, int t, int r, int b) { return ::SetRect(this, l, t, r, b); }
+ BOOL SetRect(POINT TopLeft, POINT BtmRight) { return ::SetRect(this, TopLeft.x, TopLeft.y, BtmRight.x, BtmRight.y); }
+ BOOL SetRectEmpty() { return ::SetRectEmpty(this); }
+ BOOL SubtractRect(RECT rc1, RECT rc2) { return ::SubtractRect(this, &rc1, &rc2); }
+ BOOL UnionRect(RECT rc1, RECT rc2) { return ::UnionRect(this, &rc1, &rc2); }
+
+ // Reposition rectangle
+ void MoveToX (int x) { right = Width() + x; left = x; }
+ void MoveToY (int y) { bottom = Height() + y; top = y; }
+ void MoveToXY (int x, int y) { MoveToX(x); MoveToY(y); }
+ void MoveToXY (POINT pt) { MoveToX (pt.x); MoveToY (pt.y); }
+
+ // Attributes
+ int Height() const { return bottom - top; }
+ int Width() const { return right - left; }
+ CSize Size() const { return CSize(Width(), Height()); }
+ CPoint CenterPoint() const { return CPoint((left + right) / 2, (top + bottom) / 2); }
+ CPoint TopLeft() const { return CPoint(left, top); }
+ CPoint BottomRight() const { return CPoint(right, bottom); }
+
+ // operators
+ operator LPRECT() { return this; }
+ BOOL operator == (RECT rc) const { return ::EqualRect(this, &rc); }
+ BOOL operator != (RECT rc) const { return !::EqualRect(this, &rc); }
+ void operator += (POINT pt) { ::OffsetRect(this, pt.x, pt.y); }
+ void operator += (SIZE size) { ::OffsetRect(this, size.cx, size.cy); }
+ void operator += (RECT rc) { ::InflateRect(this, rc.right - rc.left, rc.bottom - rc.top); }
+ void operator -= (RECT rc) { ::InflateRect(this, rc.left - rc.right, rc.top - rc.bottom); }
+ void operator -= (POINT pt) { ::OffsetRect(this, -pt.x, -pt.y); }
+ void operator -= (SIZE sz) { ::OffsetRect(this, -sz.cx, -sz.cy); }
+ void operator &= (RECT rc) { ::IntersectRect(this, this, &rc); }
+ void operator |= (RECT rc) { ::UnionRect(this, this, &rc); }
+
+ // Operators returning CRect
+ CRect operator + (POINT pt) const { CRect rc(*this); ::OffsetRect(&rc, pt.x, pt.y); return rc; }
+ CRect operator - (POINT pt) const { CRect rc(*this); ::OffsetRect(&rc, -pt.x, -pt.y); return rc; }
+ CRect operator + (SIZE sz) const { CRect rc(*this); ::OffsetRect(&rc, sz.cx, sz.cy); return rc; }
+ CRect operator - (SIZE sz) const { CRect rc(*this); ::OffsetRect(&rc, -sz.cx, -sz.cy); return rc; }
+ CRect operator + (RECT rc) const { CRect rc1(*this); rc1.InflateRect(rc); return rc1; }
+ CRect operator - (RECT rc) const { CRect rc1(*this); rc1.DeflateRect(rc); return rc1; }
+ CRect operator & (RECT rc) const { CRect rc1; ::IntersectRect(&rc1, this, &rc); return rc1; }
+ CRect operator | (RECT rc) const { CRect rc1; ::UnionRect(&rc1, this, &rc); return rc1; }
+ };
+
+ // CSize member function definitions
+ inline CPoint CSize::operator + (POINT pt) const { return CPoint(pt) + *this; }
+ inline CPoint CSize::operator - (POINT pt) const { return CPoint(pt) - *this; }
+ inline CRect CSize::operator + (RECT rc) const { return CRect(rc) + *this; }
+ inline CRect CSize::operator - (RECT rc) const { return CRect(rc) - *this; }
+
+ // CPoint member function definitions
+ inline CRect CPoint::operator + (RECT rc) const { return CRect(rc) + *this; }
+ inline CRect CPoint::operator - (RECT rc) const { return CRect(rc) - *this; }
+
+
+ ////////////////////////////////////////////////////////
+ // Classes and functions (typedefs) for text conversions
+ //
+ // This section defines the following text conversions:
+ // A2BSTR ANSI to BSTR
+ // A2OLE ANSI to OLE
+ // A2T ANSI to TCHAR
+ // A2W ANSI to WCHAR
+ // OLE2A OLE to ANSI
+ // OLE2T OLE to TCHAR
+ // OLE2W OLE to WCHAR
+ // T2A TCHAR to ANSI
+ // T2BSTR TCHAR to BSTR
+ // T2OLE TCHAR to OLE
+ // T2W TCHAR to WCHAR
+ // W2A WCHAR to ANSI
+ // W2BSTR WCHAR to BSTR
+ // W2OLE WCHAR to OLE
+ // W2T WCHAR to TCHAR
+
+ // About different character and string types:
+ // ------------------------------------------
+ // char (or CHAR) character types are ANSI (8 bits).
+ // wchar_t (or WCHAR) character types are Unicode (16 bits).
+ // TCHAR characters are Unicode if the _UNICODE macro is defined, otherwise they are ANSI.
+ // BSTR (Basic String) is a type of string used in Visual Basic and COM programming.
+ // OLE is the same as WCHAR. It is used in Visual Basic and COM programming.
+
+
+ // Forward declarations of our classes. They are defined later.
+ class CA2A;
+ class CA2W;
+ class CW2A;
+ class CW2W;
+ class CA2BSTR;
+ class CW2BSTR;
+
+ // typedefs for the well known text conversions
+ typedef CA2W A2W;
+ typedef CW2A W2A;
+ typedef CW2BSTR W2BSTR;
+ typedef CA2BSTR A2BSTR;
+ typedef CW2A BSTR2A;
+ typedef CW2W BSTR2W;
+
+#ifdef _UNICODE
+ typedef CA2W A2T;
+ typedef CW2A T2A;
+ typedef CW2W T2W;
+ typedef CW2W W2T;
+ typedef CW2BSTR T2BSTR;
+ typedef BSTR2W BSTR2T;
+#else
+ typedef CA2A A2T;
+ typedef CA2A T2A;
+ typedef CA2W T2W;
+ typedef CW2A W2T;
+ typedef CA2BSTR T2BSTR;
+ typedef BSTR2A BSTR2T;
+#endif
+
+ typedef A2W A2OLE;
+ typedef T2W T2OLE;
+ typedef CW2W W2OLE;
+ typedef W2A OLE2A;
+ typedef W2T OLE2T;
+ typedef CW2W OLE2W;
+
+ class CA2W
+ {
+ public:
+ CA2W(LPCSTR pStr) : m_pStr(pStr)
+ {
+ if (pStr)
+ {
+ // Resize the vector and assign null WCHAR to each element
+ int length = (int)strlen(pStr)+1;
+ m_vWideArray.assign(length, L'\0');
+
+ // Fill our vector with the converted WCHAR array
+ MultiByteToWideChar(CP_ACP, 0, pStr, -1, &m_vWideArray[0], length);
+ }
+ }
+ ~CA2W() {}
+ operator LPCWSTR() { return m_pStr? &m_vWideArray[0] : NULL; }
+ operator LPOLESTR() { return m_pStr? (LPOLESTR)&m_vWideArray[0] : (LPOLESTR)NULL; }
+ operator LPBSTR() { return m_pStr? (LPBSTR)&m_vWideArray[0] : (LPBSTR)NULL; }
+
+ private:
+ CA2W(const CA2W&);
+ CA2W& operator= (const CA2W&);
+ std::vector<wchar_t> m_vWideArray;
+ LPCSTR m_pStr;
+ };
+
+ class CW2A
+ {
+ public:
+ CW2A(LPCWSTR pWStr) : m_pWStr(pWStr)
+ {
+ // Resize the vector and assign null char to each element
+ int length = (int)wcslen(pWStr)+1;
+ m_vAnsiArray.assign(length, '\0');
+
+ // Fill our vector with the converted char array
+ WideCharToMultiByte(CP_ACP, 0, pWStr, -1, &m_vAnsiArray[0], length, NULL,NULL);
+ }
+
+ ~CW2A() {}
+ operator LPCSTR() { return m_pWStr? &m_vAnsiArray[0] : NULL; }
+
+ private:
+ CW2A(const CW2A&);
+ CW2A& operator= (const CW2A&);
+ std::vector<char> m_vAnsiArray;
+ LPCWSTR m_pWStr;
+ };
+
+ class CW2W
+ {
+ public:
+ CW2W(LPCWSTR pWStr) : m_pWStr(pWStr) {}
+ operator LPCWSTR() { return (LPWSTR)m_pWStr; }
+ operator LPOLESTR() { return (LPOLESTR)m_pWStr; }
+
+ private:
+ CW2W(const CW2W&);
+ CW2W& operator= (const CW2W&);
+
+ LPCWSTR m_pWStr;
+ };
+
+ class CA2A
+ {
+ public:
+ CA2A(LPCSTR pStr) : m_pStr(pStr) {}
+ operator LPCSTR() { return (LPSTR)m_pStr; }
+
+ private:
+ CA2A(const CA2A&);
+ CA2A& operator= (const CA2A&);
+
+ LPCSTR m_pStr;
+ };
+
+ class CW2BSTR
+ {
+ public:
+ CW2BSTR(LPCWSTR pWStr) { m_bstrString = ::SysAllocString(pWStr); }
+ ~CW2BSTR() { ::SysFreeString(m_bstrString); }
+ operator BSTR() { return m_bstrString;}
+
+ private:
+ CW2BSTR(const CW2BSTR&);
+ CW2BSTR& operator= (const CW2BSTR&);
+ BSTR m_bstrString;
+ };
+
+ class CA2BSTR
+ {
+ public:
+ CA2BSTR(LPCSTR pStr) { m_bstrString = ::SysAllocString(A2W(pStr)); }
+ ~CA2BSTR() { ::SysFreeString(m_bstrString); }
+ operator BSTR() { return m_bstrString;}
+
+ private:
+ CA2BSTR(const CA2BSTR&);
+ CA2BSTR& operator= (const CA2BSTR&);
+ BSTR m_bstrString;
+ };
+
+
+ ////////////////////////////////////////
+ // Global Functions
+ //
+
+ inline CWnd* FromHandle(HWND hWnd)
+ // Returns the CWnd object associated with the window handle
+ {
+ assert( GetApp() );
+ CWnd* pWnd = GetApp()->GetCWndFromMap(hWnd);
+ if (::IsWindow(hWnd) && pWnd == 0)
+ {
+ GetApp()->AddTmpWnd(hWnd);
+ pWnd = GetApp()->GetCWndFromMap(hWnd);
+ ::PostMessage(hWnd, UWM_CLEANUPTEMPS, 0, 0);
+ }
+
+ return pWnd;
+ }
+
+
+ inline CWinApp* GetApp()
+ // Returns a pointer to the CWinApp derrived class
+ {
+ return CWinApp::SetnGetThis();
+ }
+
+ inline CPoint GetCursorPos()
+ {
+ CPoint pt;
+ ::GetCursorPos(&pt);
+ return pt;
+ }
+
+ inline HBITMAP LoadBitmap (LPCTSTR lpszName)
+ {
+ assert(GetApp());
+
+ HBITMAP hBitmap = (HBITMAP)::LoadImage (GetApp()->GetResourceHandle(), lpszName, IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR);
+ return hBitmap;
+ }
+
+ inline HBITMAP LoadBitmap (int nID)
+ {
+ return LoadBitmap(MAKEINTRESOURCE(nID));
+ }
+
+
+ inline void TRACE(LPCTSTR str)
+ // TRACE sends a string to the debug/output pane, or an external debugger
+ {
+ #ifdef _DEBUG
+ OutputDebugString(str);
+ #else
+ UNREFERENCED_PARAMETER(str); // no-op
+ #endif
+ }
+
+ #ifndef _WIN32_WCE // for Win32/64 operating systems, not WinCE
+
+ inline int GetWinVersion()
+ {
+ DWORD dwVersion = GetVersion();
+ int Platform = (dwVersion < 0x80000000)? 2:1;
+ int MajorVer = LOBYTE(LOWORD(dwVersion));
+ int MinorVer = HIBYTE(LOWORD(dwVersion));
+
+ int nVersion = 1000*Platform + 100*MajorVer + MinorVer;
+
+ // Return values and window versions:
+ // 1400 Windows 95
+ // 1410 Windows 98
+ // 1490 Windows ME
+ // 2400 Windows NT
+ // 2500 Windows 2000
+ // 2501 Windows XP
+ // 2502 Windows Server 2003
+ // 2600 Windows Vista and Windows Server 2008
+ // 2601 Windows 7
+
+ return nVersion;
+ }
+
+ inline int GetComCtlVersion()
+ {
+ // Load the Common Controls DLL
+ HMODULE hComCtl = ::LoadLibraryA("COMCTL32.DLL");
+ if (!hComCtl)
+ return 0;
+
+ int ComCtlVer = 400;
+
+ if (::GetProcAddress(hComCtl, "InitCommonControlsEx"))
+ {
+ // InitCommonControlsEx is unique to 4.7 and later
+ ComCtlVer = 470;
+
+ if (::GetProcAddress(hComCtl, "DllGetVersion"))
+ {
+ typedef HRESULT CALLBACK DLLGETVERSION(DLLVERSIONINFO*);
+ DLLGETVERSION* pfnDLLGetVersion = NULL;
+
+ pfnDLLGetVersion = (DLLGETVERSION*)::GetProcAddress(hComCtl, "DllGetVersion");
+ if(pfnDLLGetVersion)
+ {
+ DLLVERSIONINFO dvi;
+ dvi.cbSize = sizeof dvi;
+ if(NOERROR == pfnDLLGetVersion(&dvi))
+ {
+ DWORD dwVerMajor = dvi.dwMajorVersion;
+ DWORD dwVerMinor = dvi.dwMinorVersion;
+ ComCtlVer = 100 * dwVerMajor + dwVerMinor;
+ }
+ }
+ }
+ else if (::GetProcAddress(hComCtl, "InitializeFlatSB"))
+ ComCtlVer = 471; // InitializeFlatSB is unique to version 4.71
+ }
+
+ ::FreeLibrary(hComCtl);
+
+ // return values and DLL versions
+ // 400 dll ver 4.00 Windows 95/Windows NT 4.0
+ // 470 dll ver 4.70 Internet Explorer 3.x
+ // 471 dll ver 4.71 Internet Explorer 4.0
+ // 472 dll ver 4.72 Internet Explorer 4.01 and Windows 98
+ // 580 dll ver 5.80 Internet Explorer 5
+ // 581 dll ver 5.81 Windows 2000 and Windows ME
+ // 582 dll ver 5.82 Windows XP or Vista without XP themes
+ // 600 dll ver 6.00 Windows XP with XP themes
+ // 610 dll ver 6.10 Windows Vista with XP themes
+ // 616 dll ver 6.16 Windows Vista SP1 or Windows 7 with XP themes
+
+ return ComCtlVer;
+ }
+
+ inline UINT GetSizeofMenuItemInfo()
+ {
+ UINT uSize = sizeof(MENUITEMINFO);
+ // For Win95 and NT, cbSize needs to be 44
+ if (1400 == (GetWinVersion()) || (2400 == GetWinVersion()))
+ uSize = 44;
+
+ return uSize;
+ }
+
+ inline UINT GetSizeofNonClientMetrics()
+ {
+ // This function correctly determines the sizeof NONCLIENTMETRICS
+ UINT uSize = sizeof (NONCLIENTMETRICS);
+
+ #if (WINVER >= 0x0600)
+ if (GetWinVersion() < 2600 && (uSize > 500)) // Is OS version less than Vista
+ uSize -= sizeof(int); // Adjust size back to correct value
+ #endif
+
+ return uSize;
+ }
+
+
+
+ // A global function to report the state of the left mouse button
+ inline BOOL IsLeftButtonDown()
+ {
+ SHORT state;
+ if (GetSystemMetrics(SM_SWAPBUTTON))
+ // Mouse buttons are swapped
+ state = GetAsyncKeyState(VK_RBUTTON);
+ else
+ // Mouse buttons are not swapped
+ state = GetAsyncKeyState(VK_LBUTTON);
+
+ // returns true if the left mouse button is down
+ return (state & 0x8000);
+ }
+
+ inline BOOL IsAeroThemed()
+ {
+ BOOL bIsAeroThemed = FALSE;
+
+ // Test if Windows version is XP or greater
+ if (GetWinVersion() >= 2501)
+ {
+ HMODULE hMod = ::LoadLibrary(_T("uxtheme.dll"));
+ if(hMod)
+ {
+ // Declare pointers to IsCompositionActive function
+ FARPROC pIsCompositionActive = ::GetProcAddress(hMod, "IsCompositionActive");
+
+ if(pIsCompositionActive)
+ {
+ if(pIsCompositionActive())
+ {
+ bIsAeroThemed = TRUE;
+ }
+ }
+ ::FreeLibrary(hMod);
+ }
+ }
+
+ return bIsAeroThemed;
+ }
+
+ inline BOOL IsXPThemed()
+ {
+ BOOL bIsXPThemed = FALSE;
+
+ // Test if Windows version is XP or greater
+ if (GetWinVersion() >= 2501)
+ {
+ HMODULE hMod = ::LoadLibrary(_T("uxtheme.dll"));
+ if(hMod)
+ {
+ // Declare pointers to functions
+ FARPROC pIsAppThemed = ::GetProcAddress(hMod, "IsAppThemed");
+ FARPROC pIsThemeActive = ::GetProcAddress(hMod, "IsThemeActive");
+
+ if(pIsAppThemed && pIsThemeActive)
+ {
+ if(pIsAppThemed() && pIsThemeActive())
+ {
+ // Test if ComCtl32 dll used is version 6 or later
+ bIsXPThemed = (GetComCtlVersion() >= 600);
+ }
+ }
+ ::FreeLibrary(hMod);
+ }
+ }
+
+ return bIsXPThemed;
+ }
+
+ #endif // #ifndef _WIN32_WCE
+
+ // Required for WinCE
+ #ifndef lstrcpyn
+ inline LPTSTR lstrcpyn(LPTSTR lpstrDest, LPCTSTR lpstrSrc, int nLength)
+ {
+ if(NULL == lpstrDest || NULL == lpstrSrc || nLength <= 0)
+ return NULL;
+ int nLen = MIN((int)lstrlen(lpstrSrc), nLength - 1);
+ LPTSTR lpstrRet = (LPTSTR)memcpy(lpstrDest, lpstrSrc, nLen * sizeof(TCHAR));
+ lpstrDest[nLen] = _T('\0');
+ return lpstrRet;
+ }
+ #endif // !lstrcpyn
+
+}
+
+
+#endif // _WIN32XX_WINUTILS_H_