Q: How do I choose a font size to exactly fit a string in a given rectangle?
A: Choosing font width and height by calculating the rectangle width and height will not solve this problem perfectly. This will only give a font which approximately fit in the rectangle, since characters are of different widths.
In this method, calculating the font size is done in two steps. First, rough font width and height are calculated from rectangle dimensions. This font is then selected for the display device context and exact width and height is determined. From this actual font dimensions, required font dimensions are calculated by proportionately sizing the font.
When you output multiple lines, some space is left between characters in subsequent lines ('tmExternalLeading' of 'TEXTMETRIC' structure). While evaluating the font size, this is also taken into account.
The method is wrapped into a function 'TextOut()'. This is similar to the SDK function 'TextOut', but differs in the type of arguments. First argument is handle to device context, similar to the SDK function. Second and third arguments are pointer to the rectangle and character array respectively. Here is the code, with comments sprinkled liberally:
Result is shown in the attached image. Rectangle is shown in gray shade over which the string is output in transparent mode.
Note: Most of the material in this article is taken from codeguru.com
Q: How to convert between ANSI and UNICODE strings?
A:
The quick and dirty way
This way of working is correct for codepages that are single-byte and Unicode strings that are UCS2. This applies to most cases, but if your program should run correctly on Japanese, Chinese, Taiwanese and other systems which have DBCS codepages then use the "correct way" described further below.
ANSI to UNICODE:
The conversion is done using the 'MultiByteToWideChar()'
UNICODE to ANSI:
The UNICODE string mostly is returned by some COM function, like this one:
The conversion is done using the 'WideCharToMultiByte()' function:
The correct way
If you want to handle DBCS codepages and UTF-16 Unicode strings then you should do things this way. The idea is to call 'MultiByteToWideChar()' resp. 'WideCharToMultiByte()' twice. First you get the length of the result, then you allocate the resulting string and call it again to convert.
ANSI to Unicode
Unicode to ANSI
Note: Most of the material in this article is taken from codeguru.com
Q: How can I write data to the registry?
A: To open the registry key use the function RegOpenKeyEx. To write a vaule from registry use the function RegSetValueEx.
Note: Most of the material in this article is taken from codeguru.com
Q: How can I read data from the registry?
A: To open the registry key use the function RegOpenKeyEx. To read a vaule from registry use the function RegQueryValueEx.
Q: The RegQueryValueEx function returns an error code 234 (ERROR_MORE_DATA) that means "more data is available". How many bytes must be allocated for value buffer to assure this error does not appear anymore?
A: To find the necessary buffer size, call 'RegQueryValueEx()' with a 'NULL' value in 'lpData' parameter. After return, the variable pointed by 'lpcbData' will contain the size of the data. Allocate the buffer 'lpData' then call 'RegQueryValueEx()' again:
Note: Most of the material in this article is taken from codeguru.com
Q: How to use member functions as thread functions?
A: While trying to use member functions of a class as thread functions the compiler might complain with some kind of error like
or
error C2665: 'AfxBeginThread' : none of the 2 overloads can convert parameter 1 from
type 'unsigned int (void *)'
The problem is that every thread function has its own prototype, which determines the parameters that gets passed from the operating system to it.
In C++ every member function has a hidden parameter - the so-called 'this' pointer which will be automatically passed to the function. C++ is able to associate a function with a particular instance of an object by means of the 'this' pointer. Member functions access member variables through the 'this' pointer...
This code will be compiled as
The operating system does not call thread functions through objects therefore it cannot handle the automatically added 'this' pointer... To get member functions working as thread routines you need to tell the compiler explicitly not to expect a 'this' pointer. To avoid the automatic 'this' pointer you have two possibilities:
Non-member functions are not part of a class and therefore do not have a 'this' pointer. Static member functions do not receive a this' pointer either...thus, if you want to use a member function as a thread routine you need to declare it as 'static'...
More information can be found here and here.
Note: Most of the material in this article is taken from codeguru.com
Q: How to end a thread?
A: There are different ways depending whether the thread will be ended from inside or outside. For ending a thread from inside the function 'ExitThread()' can be used.
This will end the actual thread. It is the preferred method to end a thread. This function will also be called implicitly while returning from the thread procedure and provides a clean shutdown of the thread.
To end a thread from outside there exist also two general possibilities. To provide a clean exit of the thread an event can be set which was passed as a thread parameter and which is frequently checked by the thread procedure.
If the approach described above is not possible for several reasons (e.g. a lengthy database query is performed) then the thread can be forced to exit by a call to 'TerminateThread()'.
'hThread' is the handle of the thread which can be obtained by use of any of the functions described in 'How to create a worker thread?'. On Windows NT, Windows 2000 and Windows XP systems, the handle must have 'THREAD_TERMINATE' access.
'TerminateThread()' has some drawbacks which should be considered. It causes the thread to exit. When this occurs, the thread does not have the chance to execute any user-mode code any longer. DLLs attached to the thread are not notified that the thread is terminating.
Additional information is provided by the MSDN:
Note: Most of the material in this article is taken from codeguru.com
Q: How to end a thread?
A: There are different ways depending whether the thread will be ended from inside or outside. For ending a thread from inside the function 'ExitThread()' can be used.
This will end the actual thread. It is the preferred method to end a thread. This function will also be called implicitly while returning from the thread procedure and provides a clean shutdown of the thread.
To end a thread from outside there exist also two general possibilities. To provide a clean exit of the thread an event can be set which was passed as a thread parameter and which is frequently checked by the thread procedure.
If the approach described above is not possible for several reasons (e.g. a lengthy database query is performed) then the thread can be forced to exit by a call to 'TerminateThread()'.
'hThread' is the handle of the thread which can be obtained by use of any of the functions described in 'How to create a worker thread?'. On Windows NT, Windows 2000 and Windows XP systems, the handle must have 'THREAD_TERMINATE' access.
'TerminateThread()' has some drawbacks which should be considered. It causes the thread to exit. When this occurs, the thread does not have the chance to execute any user-mode code any longer. DLLs attached to the thread are not notified that the thread is terminating.
Additional information is provided by the MSDN:
Note: Most of the material in this article is taken from codeguru.com
Q: How to create a worker thread?
A: There are several ways to create a worker thread:
The following samples will show the creation of a thread using the three functions '_beginthreadex()', 'CreateThread()' and 'AfxBeginThread()'.
Note: Most of the material in this article is taken from codeguru.com
Processes: How can I wait until a process ends?
Q: How can I wait until a process ends?
A: Depending on the method chosen for creating the process, waiting until it is finished is pretty easy to implement. 'CreateProcess()' provides handles both to the process and its primary thread within the 'PROCESS_INFORMATION' structure. The process handle can be used to wait for termination of the process:
'ShellExecuteEx()' provides only a handle to the process but unfortunately it is not guaranteed and is depending on several options you can set within the 'SHELLEXECUTEINFO' structure. For any other method used to create the process a handle to the process needs to be obtained first.
Note: Most of the material in this article is taken from codeguru.com
Q: How can I start a process ?
A: There are several ways to start a process:
Most common are 'ShellExecute()', ShellExecuteEx()' and 'CreateProcess()'. Note that 'WinExec()' is provided only for compatibility with 16-bit Windows and should not be used any longer. The following examples will show how to display the text file 'c:\example.txt' in 'notepad.exe' using these three functions...
Note: Most of the material in this article is taken from codeguru.com