The article ACC2000, How to convert Twips to Pixels, explains what you have to do. Anyway, here's the Twips2Pixels function that converts X and Y twips coordinates to pixels coordinates.
Private Declare Function GetDC Lib "user32" (ByVal hwnd As Long) As Long
Private Declare Function ReleaseDC Lib "user32" (ByVal hwnd As Long, ByVal hDC As Long) As Long
Private Declare Function GetDeviceCaps Lib "gdi32" (ByVal hDC As Long, ByVal nIndex As Long) As Long
Private Const LOGPIXELSX = 88
Private Const LOGPIXELSY = 90
' Converts twips corrdinates to pixels coordinates
Private Sub Twips2Pixels(X As Long, Y As Long)
Dim hDC As Long
hDC = GetDC(0)
X = X / 1440 * GetDeviceCaps(hDC, LOGPIXELSX)
Y = Y / 1440 * GetDeviceCaps(hDC, LOGPIXELSY)
ReleaseDC 0, hDC
End Sub
If you feel that a window is flickering while you are updating a control, you
can use the showWindow function described bellow. The function hides the window,
but do not reflect the changes ( in the container window ) until you show again
the window. The function uses the SetWindowPos API function. There is a
LockWindow API function, but it locks only a single window at a time.
' We need SetWindowPos API
Private Declare Function SetWindowPos Lib "user32" (ByVal hwnd As Long, ByVal hWndInsertAfter As Long, ByVal x As Long, ByVal y As Long, ByVal cx As Long, ByVal cy As Long, ByVal wFlags As Long) As Long
Private Const SWP_FRAMECHANGED = &H20
Private Const SWP_NOMOVE = &H2
Private Const SWP_NOREDRAW = &H8
Private Const SWP_NOSIZE = &H1
Private Const SWP_NOZORDER = &H4
Private Const SWP_SHOWWINDOW = &H40
Private Const SWP_HIDEWINDOW = &H80
Private Sub showWindow(ByVal h As Long, ByVal bShow As Boolean)
If (Not bShow) Then
SetWindowPos h, 0, 0, 0, 0, 0, SWP_NOSIZE Or SWP_NOMOVE Or SWP_NOZORDER Or SWP_HIDEWINDOW Or SWP_NOREDRAW
Else
SetWindowPos h, 0, 0, 0, 0, 0, SWP_NOSIZE Or SWP_NOMOVE Or SWP_NOZORDER Or SWP_SHOWWINDOW Or SWP_FRAMECHANGED
End If
End Sub
Sample:
showWindow List1.hwnd, False
With List1
.BeginUpdate
With .Items
.Add "Item 1"
.Add "Item 2"
.............
.Add "Item n"
End With
.EndUpdate
End With
showWindow List1.hwnd, True
Using a layered window can significantly improve performance and visual effects
for a window that has a complex shape, animates its shape, or wishes to use
alpha blending effects:
Private Declare Function SetLayeredWindowAttributes Lib "user32.dll" (ByVal hwnd As Long, ByVal crKey As Long, ByVal bAlpha As Byte, ByVal dwFlags As Long) As Boolean
Private Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Private Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long) As Long
Const LWA_ALPHA = 2
Const GWL_EXSTYLE = (-20)
Const WS_EX_LAYERED = &H80000
Private Sub Form_Load()
SetWindowLong hwnd, GWL_EXSTYLE, GetWindowLong(hwnd, GWL_EXSTYLE) Or WS_EX_LAYERED
SetLayeredWindowAttributes hwnd, 0, 128, LWA_ALPHA
End Sub
The following sample runs un Windows NT, 2000 or XP. The sample prints each
process and its modules:
Option Explicit
Private Declare Function EnumProcesses Lib "psapi" (lpIdProcess As Any, ByVal cb As Long, cbNeeded As Long) As Long
Private Declare Function EnumProcessModules Lib "psapi.dll" (ByVal hProcess As Long, ByRef lphModule As Long, ByVal cb As Long, ByRef cbNeeded As Long) As Long
Private Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal dwProcessId As Long) As Long
Private Declare Function GetModuleFileNameExA Lib "psapi.dll" (ByVal hProcess As Long, ByVal hModule As Long, ByVal ModuleName As String, ByVal nSize As Long) As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Private Const PROCESS_QUERY_INFORMATION = 1024
Private Const PROCESS_VM_READ = 16
Private Sub Form_Load()
EnumP
End Sub
Private Function onEnumM(ByVal strModule As String, ByVal asProcess As Boolean) As Boolean
onEnumM = True
If (Not asProcess) Then
strModule = " " & strModule
End If
Debug.Print strModule
End Function
Private Function EnumP() As Boolean
Dim idProcess() As Long
Dim cb As Long, I As Long
cb = 16
Do
ReDim idProcess(0 To cb - 1) As Long
If EnumProcesses(idProcess(0), cb * 4, I) = 0 Then Exit Function
If I < cb * 4 Then
ReDim idProcess(0 To (I / 4) - 1) As Long
EnumProcesses idProcess(0), cb * 4, I
Exit Do
End If
cb = cb * 2
Loop
Dim bResult As Boolean
bResult = True
For I = LBound(idProcess) To UBound(idProcess)
Dim h As Long
h = OpenProcess(PROCESS_QUERY_INFORMATION Or PROCESS_VM_READ, 0, idProcess(I))
If (h <> 0) Then
bResult = EnumM(h)
CloseHandle h
If (Not bResult) Then Exit For
End If
Next
EnumP = bResult
End Function
Private Function EnumM(ByVal hProcess As Long) As Boolean
Dim hModule() As Long
Dim cb As Long, I As Long
' If the cb is grather than 1 the procedure gets all modules of the process
cb = 2
Do
ReDim hModule(0 To cb - 1) As Long
If EnumProcessModules(hProcess, hModule(0), cb * 4, I) = 0 Then
EnumM = True
Exit Function
End If
If (cb = 1) Then Exit Do
If I < cb * 4 Then
ReDim hModule(0 To (I / 4) - 1) As Long
EnumProcessModules hProcess, hModule(0), cb * 4, I
Exit Do
End If
cb = cb * 2
Loop
For I = LBound(hModule) To UBound(hModule)
Dim s As String
s = String(1024, " ")
s = Mid(s, 1, GetModuleFileNameExA(hProcess, hModule(I), s, 1024))
If (Not onEnumM(s, I = LBound(hModule))) Then
EnumM = False
Exit Function
End If
Next
EnumM = True
End Function
The following sample displays the "My Computer" view:
Private Sub Form_Load()
Dim b As Object
Set b = Controls.Add("Shell.Explorer", "Browser", Me)
b.Object.Navigate2 "::{20D04FE0-3AEA-1069-A2D8-08002B30309D}"
b.Visible = True
End Sub
Here's MFC based tool, that's easy and free. All that you need
to do is to run the "lines.exe" file and to drag files/folders to the
right-side list box control. If you drag a folder the control enumerates all
files recursively. Change the extension masks to count only the files that you
are interested into. Click here to download the
VC project.
The VariantChangeType API function converts a VARIANT from one type to
another. The following sample uses CComVariant class to convert a VARIANT to a
string:
To find out the interfaces that a COM object implements, you have to query the
object for all registered interfaces. The windows registry holds all known
interfaces in the HKCR\Interfaces registry key. The QI::MsgBox( yourCOMObject )
displays a list of interfaces implemented by the passed object :
#include <atlbase.h>
#include <string>
#include <sstream>
class QI : protected CRegKey,
#ifdef _UNICODE
public std::wstringstream
#else
public std::stringstream
#endif
{
protected:
virtual tstring Query( IUnknown* pUnk )
{
if ( pUnk != NULL && ( ERROR_SUCCESS == Open( HKEY_CLASSES_ROOT, _T("Interface") ) ) )
{
TCHAR szKeyName[1024] = _T("");
for ( int i = 0; ERROR_SUCCESS == RegEnumKey( m_hKey, i, szKeyName, 1024 ); i++ )
{
USES_CONVERSION;
CLSID clsID = CLSID_NULL;
if ( SUCCEEDED( CLSIDFromString( T2OLE(szKeyName), &clsID ) ) )
{
CComPtr<IUnknown> spObject = NULL;
if ( SUCCEEDED( pUnk->QueryInterface( clsID, (void**)&spObject ) ) )
{
TCHAR szValue[1024] = _T(""); LONG ncbValue = 1024;
if ( ERROR_SUCCESS == RegQueryValue( m_hKey, szKeyName, szValue, &ncbValue ) )
*this << tstring(szValue) + _T("\r\n");
}
}
}
Close();
}
return str();
}
public:
static void MsgBox( IUnknown* pUnk )
{
QI objQI;
MessageBox( NULL, objQI.Query( pUnk ).c_str(), _T("The object implements:"), MB_ICONINFORMATION );
}
};
A picture object implements this interface along with IPicture to provide
access to the picture's properties through Automation. The following function
loads a picture for a file:
A picture object implements this interface along with IPicture to provide
access to the picture's properties through Automation. The following function
loads a picture for a application's resource:
Here's the definition for CAxWnd window that implements a light but powerful
container that hosts a control using IClassFactory or IClassFactory2 interfaces.
The invalidated areas accumulate in the update
region until the region is processed when the next WM_PAINT message
occurs or until the region is validated by using the ValidateRect
function. The following function forces WM_PAINT message to be
processed:
The CoCreateInstance creates a single uninitialized
object of the class associated with a specified CLSID. The following
sample takes the control's identifier and creates an object instance.
The sample doesn't use CoCreateInstance method.
The Round function performs round to even, which is different from round to
larger. The return value is the number closest to the value of expression, with
the appropriate number of decimal places. If expression is exactly halfway
between two possible rounded values, the function returns the possible rounded
value whose rightmost digit is an even number. (In a round to larger function, a
number that is halfway between two possible rounded values is always rounded to
the larger number.). Round to even is a statistically more accurate rounding
algorithm than round to larger. A possible implementation for Round function can
be found here:
long Round( double d )
{
double f = floor( d ), c = ceil(d), df = d - f, cd = c - d;
if ( df > cd )
return (long)c;
if ( df < cd )
return (long)f;
return (long)((long)f % 2 ? c : f);
}
The "\" VB operator divides two numbers and returns an integer
result. Before division is performed, numeric expressions are rounded to Byte,
Integer, or Long subtype expressions. A possible implementation for
"\" Integer Division Operator could be:
The LoadImage API function loads an icon, cursor, animated cursor, or bitmap.
The LoadIcon API function loads the specified icon resource from the executable
(.exe) file associated with an application instance. Both functions load icons
with less than 16 colors. In order to load your icon file using more colors you
have to use the LoadPicture function. The following code adds
your icon to an image list using all colors in the icon:
Prototype the function with a complete argument list and then specify
actual parameters when declaring the pointer, as follows:
type (*ptr)(parameter_list);
If the function you want to call is member of a class ( non static member ),
you have to specify the prototype like:
type (class::*ptr)(parameter_list);
The following sample declares two classes A and B, and a pointer to a
function that's not static:
class A
{
protected:
void a1()
{
// do something
}
void a2()
{
// do something
}
};
class B : public A
{
public:
typedef void (A::*callback_a)();
virtual void callA( callback_a a = A::a1 )
{
(this->*a)();
}
};
If you would try to call in the function callA something like a(), or (*a)(),
the compiler gives "error C2064: term does not evaluate to a function",
that's why you have to call explicit the this pointer like: (this->*a)().
The Windows system provides an API called IntersectRect. The IntersectRect function calculates the intersection of two source rectangles and places the coordinates of the intersection rectangle into the destination rectangle. If the source rectangles do not intersect, an empty rectangle (in which all coordinates are set to zero) is placed into the destination rectangle.
The single problem with this API seems to be when one of the source rectangles
is empty. An empty rectangle is when the width or height of the rectangle is 0.
For instance, if you have a rectangle like (0,0,10,10) , and you want the
intersection with (5,5,5,5) rectangle, the IntersectRect API gives (0,0,0,0),
instead (5,5,5,5) that's actually not what we are looking for so the following
function just gives you the correct intersection:
// Function name : IntersectRectFix
// Description : The IntersectRect function calculates the intersection of two source rectangles and places the coordinates of the intersection rectangle into the destination rectangle.
// Return type : RECT
// Argument : RECT* prtA
// Argument : RECT* prtB
BOOL IntersectRectFix( RECT* prtResult, RECT* prtA, RECT* prtB )
{
RECT rtEmpty = {0}, rtResult = rtEmpty;
rtResult.left = min(max(prtA->left, prtB->left),prtB->right);
rtResult.right = max(min(prtA->right, prtB->right),prtB->left);
rtResult.top = min(max(prtA->top, prtB->top),prtB->bottom);
rtResult.bottom = max(min(prtA->bottom, prtB->bottom),prtB->top);
*prtResult = rtEmpty;
RECT* p = prtA;
for ( long i = 0; i < 2; i++, p = prtB )
if ( !( ( ( rtResult.left >= p->left ) && ( rtResult.right <= p->right ) ) && ( ( rtResult.top >= p->top ) && ( rtResult.bottom <= p->bottom ) ) ) )
return FALSE;
*prtResult = rtResult;
return TRUE;
}
The following function gets the EMF format (CF_ENHMETAFILE) from the clipboard and saves it to a
picture file ( EMF file ). You can use a graphic viewer to view EMF files, like
MS Paint, MS Office Picture Manager, and so on. Also, you can drag and drop the
file from the Windows Explorer to Microsoft Word, or OLE compliant
applications.
The following function saves an EMF file as a BMP file. The szEMFFile indicates
the file name of the EMF file to be read, while the szBMPFile is the file name
of the BMP file to be created. The nWidth and nHeight parameters indicates the
size of the BMP to be created. If -1 is used, the BMP size will be getting from
the bounding rectangle of the EMF header:
The VariantChangeType API function converts a VARIANT from one type to
another. The following sample uses CComVariant class to convert a VARIANT to a
string: