Home   Notes   Contact Me

Windows Programming

Local

External


Killing another process

Sometimes you need to activate a privilege you have to do this.

Microsoft Article "How to obtain a handle to any process with SeDebugPrivilege" http://support.microsoft.com/kb/q131065/

Other related articles


Windows Event Log

This article says how to set up a project to automatically do steps needed to talk to the event log, and while it does that it shows how to use the log http://www.codeproject.com/system/mctutorial.asp


Registering a Custom Protocol

Info: http://msdn.microsoft.com/library/default.asp?url=/workshop/networking/pluggable/overview/appendix_a.asp

Example

This makes note:c:\log.txt try to open, in notepad, the file note:c:\log.txt So obviously you need to make your app chop off the beginning part note:

Windows Registry Editor Version 5.00 [HKEY_CLASSES_ROOT\note] @="URL:JBP Note Protocol" "URL Protocol"="" [HKEY_CLASSES_ROOT\note\DefaultIcon] @="notepad.exe" [HKEY_CLASSES_ROOT\note\shell] [HKEY_CLASSES_ROOT\note\shell\open] [HKEY_CLASSES_ROOT\note\shell\open\command] @="\"C:\\Windows\\notepad.exe\" \"%1\""

Privilege Seperation

Doing things as a different User than original process

Doing things as a different User than original process


Network name, how to determine it for a mapped drive

Use WNetGetUniversalName


Error Codes, WinInet (12001 - 12156)

Base info: http://support.microsoft.com/default.aspx?scid=kb;EN-US;193625


   Code        Error Message and Description
   -----       -----------------------------
   12001       ERROR_INTERNET_OUT_OF_HANDLES
               No more handles could be generated at this time.

   12002       ERROR_INTERNET_TIMEOUT
               The request has timed out.

   12003       ERROR_INTERNET_EXTENDED_ERROR
               An extended error was returned from the server. This is
               typically a string or buffer containing a verbose error
               message. Call InternetGetLastResponseInfo to retrieve the
               error text.

   12004       ERROR_INTERNET_INTERNAL_ERROR
               An internal error has occurred.

   12005       ERROR_INTERNET_INVALID_URL
               The URL is invalid.

   12006       ERROR_INTERNET_UNRECOGNIZED_SCHEME
               The URL scheme could not be recognized or is not supported.

   12007       ERROR_INTERNET_NAME_NOT_RESOLVED
               The server name could not be resolved.

   12008       ERROR_INTERNET_PROTOCOL_NOT_FOUND
               The requested protocol could not be located.

   12009       ERROR_INTERNET_INVALID_OPTION
               A request to InternetQueryOption or InternetSetOption
               specified an invalid option value.

   12010       ERROR_INTERNET_BAD_OPTION_LENGTH
               The length of an option supplied to InternetQueryOption or
               InternetSetOption is incorrect for the type of option
               specified.

   12011       ERROR_INTERNET_OPTION_NOT_SETTABLE
               The request option cannot be set, only queried.

   12012       ERROR_INTERNET_SHUTDOWN
               The Win32 Internet function support is being shut down or
               unloaded.

   12013       ERROR_INTERNET_INCORRECT_USER_NAME
               The request to connect and log on to an FTP server could
               not be completed because the supplied user name is
               incorrect.

   12014       ERROR_INTERNET_INCORRECT_PASSWORD
               The request to connect and log on to an FTP server could
               not be completed because the supplied password is
               incorrect.

   12015       ERROR_INTERNET_LOGIN_FAILURE
               The request to connect to and log on to an FTP server
               failed.

   12016       ERROR_INTERNET_INVALID_OPERATION
               The requested operation is invalid.

   12017       ERROR_INTERNET_OPERATION_CANCELLED
               The operation was canceled, usually because the handle on
               which the request was operating was closed before the
               operation completed.

   12018       ERROR_INTERNET_INCORRECT_HANDLE_TYPE
               The type of handle supplied is incorrect for this
               operation.

   12019       ERROR_INTERNET_INCORRECT_HANDLE_STATE
               The requested operation cannot be carried out because the
               handle supplied is not in the correct state.

   12020       ERROR_INTERNET_NOT_PROXY_REQUEST
               The request cannot be made via a proxy.

   12021       ERROR_INTERNET_REGISTRY_VALUE_NOT_FOUND
               A required registry value could not be located.

   12022       ERROR_INTERNET_BAD_REGISTRY_PARAMETER
               A required registry value was located but is an incorrect
               type or has an invalid value.

   12023       ERROR_INTERNET_NO_DIRECT_ACCESS
               Direct network access cannot be made at this time.

   12024       ERROR_INTERNET_NO_CONTEXT
               An asynchronous request could not be made because a zero
               context value was supplied.

   12025       ERROR_INTERNET_NO_CALLBACK
               An asynchronous request could not be made because a
               callback function has not been set.

   12026       ERROR_INTERNET_REQUEST_PENDING
               The required operation could not be completed because one
               or more requests are pending.

   12027       ERROR_INTERNET_INCORRECT_FORMAT
               The format of the request is invalid.

   12028       ERROR_INTERNET_ITEM_NOT_FOUND
               The requested item could not be located.

   12029       ERROR_INTERNET_CANNOT_CONNECT
               The attempt to connect to the server failed.

   12030       ERROR_INTERNET_CONNECTION_ABORTED
               The connection with the server has been terminated.

   12031       ERROR_INTERNET_CONNECTION_RESET
               The connection with the server has been reset.

   12032       ERROR_INTERNET_FORCE_RETRY
               Calls for the Win32 Internet function to redo the request.

   12033       ERROR_INTERNET_INVALID_PROXY_REQUEST
               The request to the proxy was invalid.

   12036       ERROR_INTERNET_HANDLE_EXISTS
               The request failed because the handle already exists.

   12037       ERROR_INTERNET_SEC_CERT_DATE_INVALID
               SSL certificate date that was received from the server is
               bad. The certificate is expired.

   12038       ERROR_INTERNET_SEC_CERT_CN_INVALID
               SSL certificate common name (host name field) is incorrect.
               For example, if you entered www.server.com and the common
               name on the certificate says www.different.com.

   12039       ERROR_INTERNET_HTTP_TO_HTTPS_ON_REDIR
               The application is moving from a non-SSL to an SSL
               connection because of a redirect.

   12040       ERROR_INTERNET_HTTPS_TO_HTTP_ON_REDIR
               The application is moving from an SSL to an non-SSL
               connection because of a redirect.

   12041       ERROR_INTERNET_MIXED_SECURITY
               Indicates that the content is not entirely secure. Some of
               the content being viewed may have come from unsecured
               servers.

   12042       ERROR_INTERNET_CHG_POST_IS_NON_SECURE
               The application is posting and attempting to change
               multiple lines of text on a server that is not secure.

   12043       ERROR_INTERNET_POST_IS_NON_SECURE
               The application is posting data to a server that is not
               secure.

   12110       ERROR_FTP_TRANSFER_IN_PROGRESS
               The requested operation cannot be made on the FTP session
               handle because an operation is already in progress.

   12111       ERROR_FTP_DROPPED
               The FTP operation was not completed because the session was
               aborted.

   12130       ERROR_GOPHER_PROTOCOL_ERROR
               An error was detected while parsing data returned from the
               gopher server.

   12131       ERROR_GOPHER_NOT_FILE
               The request must be made for a file locator.

   12132       ERROR_GOPHER_DATA_ERROR
               An error was detected while receiving data from the gopher
               server.

   12133       ERROR_GOPHER_END_OF_DATA
               The end of the data has been reached.

   12134       ERROR_GOPHER_INVALID_LOCATOR
               The supplied locator is not valid.

   12135       ERROR_GOPHER_INCORRECT_LOCATOR_TYPE
               The type of the locator is not correct for this operation.

   12136       ERROR_GOPHER_NOT_GOPHER_PLUS
               The requested operation can only be made against a Gopher+
               server or with a locator that specifies a Gopher+
               operation.

   12137       ERROR_GOPHER_ATTRIBUTE_NOT_FOUND
               The requested attribute could not be located.

   12138       ERROR_GOPHER_UNKNOWN_LOCATOR
               The locator type is unknown.

   12150       ERROR_HTTP_HEADER_NOT_FOUND
               The requested header could not be located.

   12151       ERROR_HTTP_DOWNLEVEL_SERVER
               The server did not return any headers.

   12152       ERROR_HTTP_INVALID_SERVER_RESPONSE
               The server response could not be parsed.

   12153       ERROR_HTTP_INVALID_HEADER
               The supplied header is invalid.

   12154       ERROR_HTTP_INVALID_QUERY_REQUEST
               The request made to HttpQueryInfo is invalid.

   12155       ERROR_HTTP_HEADER_ALREADY_EXISTS
               The header could not be added because it already exists.

   12156       ERROR_HTTP_REDIRECT_FAILED
               The redirection failed because either the scheme changed
               (for example, HTTP to FTP) or all attempts made to redirect
               failed (default is five attempts).

Heap Debugging

// show what settings are in effect
gflags -p

// turn on ?all? for your app
gflags -p /enable myapp.exe /full

// show setting for 'myapp.exe'???
gflags -i myapp.exe

Misc Info


Debugging


Resizing a Window

Use:
MoveWindow( HWND hwnd, int X, int Y, int wide, int tall, BOOL isRepaint)


  • Libraries, looking at what is in them


    DLL's loading from memory

    http://www.joachim-bauch.de/tutorials/load_dll_memory.html/en

    Signals


    Services, How to write one

    article http://weblogs.asp.net/kennykerr/archive/2004/05/18/134342.aspx

    Reference article http://www.gamedev.net/reference/articles/article1899.asp


    OLESTR


    Naming Threads

    typedef struct tagTHREADNAME_INFO
    {
       DWORD dwType; // must be 0x1000
       LPCSTR szName; // pointer to name (in user addr space)
       DWORD dwThreadID; // thread ID (-1=caller thread)
       DWORD dwFlags; // reserved for future use, must be zero
    } THREADNAME_INFO;
    
    // dwThreadID = -1 sets the current threads name
    void ThreadStuff::SetThreadName( LPCSTR szThreadName, DWORD dwThreadID = -1)
    {
       THREADNAME_INFO info;
       info.dwType = 0x1000;
       info.szName = szThreadName;
       info.dwThreadID = dwThreadID;
       info.dwFlags = 0;
    
       __try
       {
          RaiseException( 0x406D1388, 0, sizeof(info)/sizeof(DWORD), (DWORD*)&info );
       }
    __except(EXCEPTION_CONTINUE_EXECUTION)
    {
    }
    }
    

    'interface' is not defined

    'interface' is defined in ObjBase.h if you define


    Mutex

    #include <windows.h>
    
    HANDLE mutex = CreateMutex( 0, false, "Some Name");
    
    WaitForSingleObject( mutex, timeOutInMillis);
    ReleaseMutex( mutex);
    
    WaitForSingleObject( mutex, INFINITE);
    ReleaseMutex( mutex);
    
    CloseHandle( mutex);
    

    Threads

    See Also:

    See Also External:

    // Make sure project is set to Multi Threaded, or it won't find _beginthread
    #include <process.h>
    
    void ThreadFunc( void *pData)
    {
    }
    
    void startFunc()
    {
    	_beginthread( ThreadFunc, 0, pData);
    }
    

    Misc

    SetWindowExtEx
    use it to make the pixel to windows size ratio 1::1
    
    WindowInfo
    use it to get the pixel size of the window
    

    dllUsage

    FunctionDescription
    HMODULE ::LoadLibrary( const char *zDllName)
    FARPROC ::GetProcAddress( HMODULE, const char *zProcName)

    Registry Manipulation


    Directory Functions

    FunctionDescription
    _chdir( const char* zdir)Change Directory
    FindFirstFile
    FindFirstFileEx

    Accessing development tools from a cmd shell

    "C:\Program Files\Microsoft Visual Studio .NET\Common7\Tools\vsvars32.bat"
    

    Thread Safe Helper Functions

    InterlockedIncrement
    InterlockedDecrement
    InterlockedCompareExchange
    ...
    

    Time functions

    // returns number of milliseconds since the system was started
    GetTickCount()
    
    // is defined in some windows header, so use this if you don't want to include it:
    DWORD GetTickCount(VOID);
    

    Memory Debugging

    #include <crtdbg.h>

    FunctionDescription
    long _CrtSetBreakAlloc(long allocNum);Makes the Debugger Break when memory allocation # allocNum is allocated, returns previous setting
    int _CrtCheckMemory(long allocNum);returns 0 if heap looks corrupted
    int _CrtSetDbgFlag( int flagBits);Sets memory debug settings, returns previous settings

    _CrtSetDbgFlag flag bits

    #define _CRTDBG_REPORT_FLAG         -1    /* Query bitflag status */
    #define _CRTDBG_ALLOC_MEM_DF        0x01  /* Turn on debug allocation */
    #define _CRTDBG_DELAY_FREE_MEM_DF   0x02  /* Don't actually free memory */
    #define _CRTDBG_CHECK_ALWAYS_DF     0x04  /* Check heap every alloc/dealloc */
    #define _CRTDBG_RESERVED_DF         0x08  /* Reserved - do not use */
    #define _CRTDBG_CHECK_CRT_DF        0x10  /* Leak check/diff CRT blocks */
    #define _CRTDBG_LEAK_CHECK_DF       0x20  /* Leak check at program exit */
    #define _CRTDBG_CHECK_EVERY_16_DF   0x00100000  /* check heap every 16 heap ops */
    #define _CRTDBG_CHECK_EVERY_128_DF  0x00800000  /* check heap every 128 heap ops */
    #define _CRTDBG_CHECK_EVERY_1024_DF 0x04000000  /* check heap every 1024 heap ops */
    #define _CRTDBG_CHECK_DEFAULT_DF    _CRTDBG_CHECK_EVERY_1024_DF
    

    Example

    #include <crtdbg.h>
    
    // Get current flag
    int tmpFlag = _CrtSetDbgFlag( _CRTDBG_REPORT_FLAG );
    
    // Turn on leak-checking bit
    tmpFlag |= _CRTDBG_LEAK_CHECK_DF;
    
    // Turn off CRT block checking bit
    tmpFlag &= ~_CRTDBG_CHECK_CRT_DF;
    
    // Set flag to the new value
    _CrtSetDbgFlag( tmpFlag );
    
    _CrtCheckMemory();
    
    if ( _CrtIsValidHeapPointer(*ptr) == false) {
    	cout << "It is bad" << endl;
    }
    
    _CrtMemState g_memState;
    _CrtMemCheckpoint( &LeicaGeosystems::ClientServer::g_memState);
    
    // Do lots of stuff
    
    // leak detection
    _CrtMemDumpAllObjectsSince(&LeicaGeosystems::ClientServer::g_memState);
    
    ms-help://MS.VSCC/MS.MSDNVS/dnvc60/html/memleaks.htm

    Size of a Text String

    Make sure the correct font is in the dc HFONT hFontOrig = (HFONT) SelectObject(hcd, hFont);

    ::DrawText( hdc, str, len, &rect, DT_CALCRECT);Gets bounds in pixels.
    ::GetTextExtentPoint32(...);Gets bounds in logical display units.

    Font Stuff


    Idle Processing

    Do it yourself idle processing

    // Create your idle message:
    #define WM_JBP_IDLE WM_USER + 1
    
    // In WindowProc when there is nothing queued, send it
    LRESULT Class::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
    {
    	DWORD QueueStatus;
    	LRESULT resValue = 0;
    	bool OnIdleRetVal = true;
    
    	if (message == WM_JBP_IDLE) {
    		JbpOnIdle();
    		wParam = 0;
    	} else {
    		switch( message) {
    			case WM_ACTIVATE:
    				switch( wParam) {
    					case WA_ACTIVE:
    						m_active = true;
    						break;
    					case WA_INACTIVE:
    						m_active = false;
    						break;
    				};
    				break;
    		}
    		resValue = CDialog::WindowProc(message, wParam, lParam);
    	}
    
    	QueueStatus = GetQueueStatus(QS_ALLINPUT);
    
    	if ( m_active && (HIWORD(QueueStatus) == 0) ) {
    		PostMessage(WM_JBP_IDLE, wParam + (OnIdleRetVal ? 1 : 0), 0);
    	}
    
    	return resValue;
    }
    
    
    
    

    Focus, Window focus handling

    MessagewParamdesc
    WM_ACTIVATEWA_ACTIVEHappens when the window gets focus
    WA_INACTIVEHappens when the window loses focus
    WM_FOCUS??? don't know, maybe if a control in the window gets focus ???

    Gotchas

    WM_PAINT keeps getting called

    This will happen if you don't call both ::BeginPaint() and ::EndPaint()

    Dialog Creation keeps failing

    This happens if one of the controls is a CONTROL (look in the .rc file to see). It is a common control and common controls need to be initialized with ::InitCommonControls(); [progress control is a common control]

    delete crash, deleting a class defined in a dll and exported causes a fault in memory heap


    Font Enumeration Info


    Resource DLL

    Producing a Resource DLL

    1. Create an empty DLL project
    2. Add the RC file and related resource files to the project
    3. Adjust linker settings to include the /NOENTRY option

    Multilingual Resource script:

    #include <winnt.h>
    #include "resource.h"
    
    LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
    #pragma code_page(1252)
    STRINGTABLE DISCARDABLE
    	BEGIN
    	IDS_HelloWorld "English"
    	END
    	
    LANGUAGE LANG_GERMAN, SUBLANG_GERMAN
    #pragma code_page(1252)
    STRINGTABLE DISCARDABLE
    	BEGIN
    	IDS_HelloWorld "German"
    	END
    

    Using a Resource DLL (language based example)

    TCHAR fmt[] = _T("ch09k_%04x.dll");
    TCHAR name[MAX_PATH];
    
    LCID lcid = 0x407;  // German Locale ID
    LANGID lang = LANGFROMLCID(lcid);
    
    _stprintf( name, fmt, lang);
    // name should be like this: "ch09k_0407.dll"
    
    HMODULE hRes = LoadLibraryEx( name, 0, LOAD_LIBRARY_AS_DATAFILE);
    SetThreadLocale( lcid);
    int ret = LoadString( hRes, IDS_HelloWorld, b, sizeof(b)/sizeof(TCHAR));
    
    ...
    
    SetThreadLocale( lcidDefault);
    if ( hRes != hModule) {
      FreeLibrary(hRes);
    }
    

    Charset Neutral Programming

    These work with SBCS, MBCS, and Wide char sets:
    TCHAR str[] = _T("This is a string");
    int len = tSizeOf( str);  // doesn't work for MBCS
    

    Language

    TermDescription
    LCIDLocale Identifier, pronounced 'el-cid'
    ML API
    Win32 ML API
    Multilingual API
    NLS API
    Win32 NLS API
    National Language Support API

    LCID bits:

    Purpose: Unused Sort Version Sort Sublanguage Language
    Bit Range: 3124 2320 1916 1510 90

    Examples

    LANGID x = MAKELANGID( LANG_ENGLISH, SUBLANG_ENGLISH_UK);
    LANGID xPrimary = PRIMARYLANGID(x);
    LANGID xSecondary = SUBLANGID(x);
    
    #define LANG_SYSTEM_DEFAULT (MAKELANGID(LANG_NEUTRAL,SUBLANG_SYS_DEFAULT))
    #define LANG_USER_DEFAULT   (MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT))
    
    LANGID langGermanSwiss = MAKELANGID( LANG_GERMAN, SUBLANG_GERMAN_SWISS);
    LCID lcidGerman = MAKELCID( langGermanSwiss, SORT_GERMAN_PHONE_BOOK);
    SORTID sortid = SORIDFROMLCID(lcidGerman);
    

    Gotchas


    Console

    SetConsoleModeCan make it process a char at a time, instead of a line at a time.

    Use the following code

    It should work with all styles of printing ( printf, cout ) and inputting.

    // put this near the start up of the program
    
    #ifdef _DEBUG
    	RedirectIOToConsole();
    #endif
    
    // Header file: guicon.h
    #ifndef __GUICON_H__
    #define __GUICON_H__
    
    #ifdef _DEBUG
    	void RedirectIOToConsole();
    #endif
    
    #endif
    
    // C++ file: guicon.cpp
    
    #include "stdafx.h"
    
    #include <windows.h>
    #include <stdio.h>
    #include <fcntl.h>
    #include <io.h>
    #include <iostream>
    #include <fstream>
    
    #ifndef _USE_OLD_IOSTREAMS
    using namespace std;
    #endif
    
    // maximum mumber of lines the output console should have
    static const WORD MAX_CONSOLE_LINES = 500;
    
    #ifdef _DEBUG
    
    void RedirectIOToConsole()
    {
    	int hConHandle;
    	long lStdHandle;
    
    	CONSOLE_SCREEN_BUFFER_INFO coninfo;
    	FILE *fp;
    
    	// allocate a console for this app
    	AllocConsole();
    
    	// set the screen buffer to be big enough to let us scroll text
    	GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &coninfo);
    	coninfo.dwSize.Y = MAX_CONSOLE_LINES;
    	SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), coninfo.dwSize);
    
    	// redirect unbuffered STDOUT to the console
    	lStdHandle = (long)GetStdHandle(STD_OUTPUT_HANDLE);
    	hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
    	fp = _fdopen( hConHandle, "w" );
    	*stdout = *fp;
    	setvbuf( stdout, NULL, _IONBF, 0 );
    
    	// redirect unbuffered STDIN to the console
    	lStdHandle = (long)GetStdHandle(STD_INPUT_HANDLE);
    	hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
    	fp = _fdopen( hConHandle, "r" );
    	*stdin = *fp;
    	setvbuf( stdin, NULL, _IONBF, 0 );
    
    	// redirect unbuffered STDERR to the console
    	lStdHandle = (long)GetStdHandle(STD_ERROR_HANDLE);
    	hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
    	fp = _fdopen( hConHandle, "w" );
    	*stderr = *fp;
    	setvbuf( stderr, NULL, _IONBF, 0 );
    
    	// make cout, wcout, cin, wcin, wcerr, cerr, wclog and clog 
    	// point to console as well
    	ios::sync_with_stdio();
    }
    
    #endif
    

    Menu, Adding one

    case WM_COMMAND:
    {
    	switch( wParam) {
    		case ID_FILE_EXIT:
    			::MessageBox( NULL, "a", "b", MB_OK);
    			// let windows know we processed it:
    			return 0;
    	}
    }
    break;
    

    Dialog Based Project, adding a Menu


    Font, Creating of a Certain pixel height

    [This is good for getting a font of a specific size to render into a bitmap to later use to draw the characters]

    [It Makes sure windows doesn't scale the font (which is especially bad with a raster font)]

    Best I can tell, windows doesn't let you do this. You always have to create a font by Logical Unit size (this is the size you see while graphically designing a dialog box in Visual Studio).

    You need to set the Mapping Mode to 'MM_TEXT', so that one logical unit is mapped to 1 device pixel (use 'SetMapMode') to do this

    Now windows is not going to make the font the size you want, so if you want a 12 point font to be 12 pixels tall, you have to cancel out the logical pixel size (which is normally 96 pixels per inch [or 120 if large characters are set from the display card settings dialog). These logical pixels are sized to make a 12 point font have the same angular size as they would have on a piece of paper, assuming the paper was held a normal distance from the eye, which windows considers to be closer than the normal distance you would be from a monitor. Use this formula to determine the logical pixel size for the font (oh and if you care what the logical pixel size per inch the display thinks it is, use GetDeviceCaps and look at LOGPIXELSX and LOGPIXELSY)

    int pointsToUse = -MulDiv(m_points, GetDeviceCaps(hdc, LOGPIXELSY), 72);
    

    The negative sign is used so that CreateFont will get a font of the size you request, instead of one whose bounds fit inside the size you specify


    Font, Raster Fonts

    FontSize(s)
    System10
    FixedSys9
    Terminal5, 6, 9, 12, 14
    Courier10, 12, 15
    MS Serif6, 7, 8, 10, 12, 14, 18, 24
    MS Sans Serif8, 10, 12, 14, 18, 24
    Small Fonts2, 3, 4, 5, 6, 7

    Font Sizes

    SSizeEnumCbData *pCbData = (SSizeEnumCbData*) lParam;
    std::vector<int> &vSizes = *(pCbData->m_pVector);
    
    static int truetypesize[] = { 8, 9, 10, 11, 12, 14, 16, 18, 20, 22, 24, 26, 28, 36, 48, 72 };
    
    if( FontType != TRUETYPE_FONTTYPE)
    {
    int  logsize    = lpntme->ntmTm.tmHeight - lpntme->ntmTm.tmInternalLeading;
    long pointsize  = MulDiv(logsize, 72, GetDeviceCaps(pCbData->m_hdc, LOGPIXELSY));
    
    for( int i = 0; i < (int)vSizes.size(); i++) {
      if ( vSizes[i] == pointsize) {
        return 1;
      }
    }
    vSizes.push_back( pointsize);
    if ( vSizes.size() > 100) {
      // too many sizes to be useful
      return 0;
    }
    

    ComboBox

    TypeDescription
    DropdownNormal editable
    Drop ListNormal not editable
    Simple?? and editable

    Client Window, Making one in a Wizard Generated Dialog Based Project

    This if for taking a Wizard Generated Dialog Based Project, then definint an area you want a custom child window to be at, and then making that child window.

    WNDCLASSEX	wc;
    
    wc.cbSize        = sizeof( WNDCLASSEX);
    wc.style         = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
    wc.cbClsExtra    = 0;
    wc.cbWndExtra    = 0;
    wc.lpfnWndProc   = &WindowProc2;
    wc.hInstance     = AfxGetInstanceHandle();
    wc.hbrBackground = (HBRUSH) GetStockObject( WHITE_BRUSH);
    wc.hIcon         = LoadIcon( NULL, IDI_APPLICATION);
    wc.hIconSm       = LoadIcon( NULL, IDI_HAND);
    wc.hCursor       = LoadCursor( NULL, IDC_CROSS);
    wc.lpszMenuName  = NULL;
    wc.lpszClassName = strAppName;
    
    RegisterClassEx( &wc);
    
    RECT rectOuter;
    RECT rectInsideDecorations;
    GetWindowRect( &rectOuter);
    GetClientRect( &rectInsideDecorations); // right size, but at 0,0
    ClientToScreen( &rectInsideDecorations); // bounds controls are relative to
    
    int xoff = rectOuter.left - rectInsideDecorations.left;
    int yoff = rectOuter.top  - rectInsideDecorations.top;
    
    RECT targetRect;
    m_CustomClientBounds1.GetWindowRect( &targetRect);
    
    int x = targetRect.left + xoff;
    int y = targetRect.top  + yoff;
    int w = targetRect.right  - targetRect.left + 1;
    int t = targetRect.bottom - targetRect.top  + 1;
    
    //GetSystemMetrics();
    
    HWND child;
    
    child = CreateWindowEx(
      NULL,
      strAppName,
      strAppName,
      WS_CHILD | WS_VISIBLE,
      x,      // x pos
      y,      // y pos
      w,      // wide
      t,      // tall
      this->GetSafeHwnd(),
      NULL,          // Handle to Menu
      AfxGetInstanceHandle(), //hInstance,
      NULL
    );
    
    WINDOWPROC
    LRESULT CALLBACK WindowProc2( HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
    {
      switch( uMessage) {
    
        case WM_PAINT:
          {
            PAINTSTRUCT ps;
            HDC hdc;
            hdc = ::BeginPaint( hWnd, &ps);
    
            ::EndPaint( hWnd, &ps);
          }
    
          return 0;
    
        default:
          return ::DefWindowProc( hWnd, uMessage, wParam, lParam);
      }
    }