diff options
author | Petr Mrázek <peterix@gmail.com> | 2013-12-02 00:55:24 +0100 |
---|---|---|
committer | Petr Mrázek <peterix@gmail.com> | 2013-12-02 00:55:24 +0100 |
commit | 6aa9bd0f77dcb5128167fae62e32aa5252fe85c6 (patch) | |
tree | 632994a61888929af9289927d338bd19a2b3f32c /mmc_updater/depends | |
parent | 613699b3626aea750093ab7eaaeccaa28c0e87c6 (diff) | |
download | MultiMC-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')
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 + & & + < < + > > + " " + ' ' +@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 & 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 " " or " " 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. + // © -- 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 ] = +{ + { "&", 5, '&' }, + { "<", 4, '<' }, + { ">", 4, '>' }, + { """, 6, '\"' }, + { "'", 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_ |