2007年5月29日
原文地址:http://msdn.microsoft.com/library/en-us/dllproc/base/dynamic_link_library_redirection.asp
参考: http://msdn2.microsoft.com/en-us/library/aa376414.aspx
Dll重定向(动态链接库)
Applications can depend on a specific version of a shared DLL and start to fail if another application is installed with a newer or older version of the same DLL. There are two ways to ensure that your application uses the correct DLL: DLL redirection and side-by-side components. Developers and administrators should use DLL redirection for existing applications, because it does not require any changes to the application. If you are creating a new application or updating an application and want to isolate your application from potential problems, create a side-by-side component.
To use DLL redirection, create a redirection file for your application. The redirection file must be named as follows: App_name.local. For example, if the application name is Editor.exe, the redirection file should be named Editor.exe.local. You must install the .local file in the application directory. You must also install the DLLs in the application directory.
The contents of a redirection file are ignored, but its presence causes Windows to check the application directory first whenever it loads a DLL, regardless of the path specified to LoadLibrary or LoadLibraryEx. If the DLL is not found in the application directory, then these functions use their usual search order. For example, if the application c:\myapp\myapp.exe calls LoadLibrary using the following path:
c:\program files\common files\system\mydll.dll
And, if both c:\myapp\myapp.exe.local and c:\myapp\mydll.dll exist, LoadLibrary loads c:\myapp\mydll.dll. Otherwise, LoadLibrary loads c:\program files\common files\system\mydll.dll.
Alternatively, if a directory named c:\myapp\myapp.exe.local exists and contains mydll.dll, LoadLibrary loads c:\myapp\myapp.exe.local\mydll.dll.
Known DLLs cannot be redirected. For a list of known DLLs, see the following registry key: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\KnownDLLs. The system uses Windows File Protection to ensure that system DLLs such as these are not updated or deleted except by operating system (OS) updates such as service packs.
Windows 2000: Known DLLs can be redirected in this OS.
If the application has a manifest, then any .local files are ignored.
Windows 2000: Manifests do not affect DLL redirection.
- If you are using DLL redirection and the application does not have access to all drives and directories in the search order, LoadLibrary stops searching as soon as access is denied.
- If you are not using DLL redirection, LoadLibrary skips directories that it cannot access and then continues searching.
It is good practice to install application DLLs in the same directory that contains the application, even if you are not using DLL redirection. This ensures that installing the application does not overwrite other copies of the DLL and cause other applications to fail. Also, if you follow this good practice, other applications do not overwrite your copy of the DLL and cause your application to fail.
原文地址 :
http://msdn2.microsoft.com/en-us/library/aa376307.aspx
Side-by-side Assemblies
A Windows side-by-side assembly is described by manifests. A side-by-side assembly contains a collection of resources—a group of DLLs, Windows classes, COM servers, type libraries, or interfaces—that are always provided to applications together. These are described in the assembly manifest.
Typically, a side-by-side assembly is a single DLL. For example, the Microsoft COMCTL32 assembly is a single DLL with a manifest whereas the Microsoft Visual C++ development system run-time libraries assembly contains multiple files. Manifests contain metadata that describes side-by-side assemblies and side-by-side assembly dependencies.
Side-by-side assemblies are used by the operating system as fundamental units of naming, binding, versioning, deployment, and configuration. Every side-by-side assembly has a unique identity. One of the attributes of the assembly identity is its version. For more information, see Assembly Versions.
Starting with Windows XP, multiple versions of side-by-side assemblies can be used by applications running at the same time. Manifests, and the assembly version number, are used by the loader to determine the correct binding of assembly versions to applications. Side-by-side assemblies and manifests work with applications and the side-by-side manager as illustrated in the following figure.
In the preceding example, both Comctl32.DLL version 6.0 and Comctl32.DLL version 5.0 are in the side-by-side assembly cache and available to applications. When an application calls to load the DLL, the side-by-side manager determines whether the application has a version dependence described in a manifest. If there is no relevant manifest, the system loads the default version of the assembly. For Windows XP, version 5.0 of Comctl32.DLL is the system default. If the side-by-side manager finds a dependence on version 6.0 stated in a manifest, that version is loaded to run with the application.
Manifest File Schema
The following is the complete listing of the manifest file schema.
<?xml version="1.0" ?>
<Schema xmlns="urn:schemas-microsoft-com:xml-data" xmlns:dt="urn:schemas-microsoft-com:datatypes" name="urn:schemas-microsoft-com:asm.v1">
<!-- Attributes
-->
<AttributeType name="manifestVersion" dt:type="enumeration" dt:values="1.0" />
<AttributeType name="name" dt:type="string" />
<AttributeType name="type" dt:type="string" />
<AttributeType name="publicKeyToken" dt:type="bin.hex" />
<AttributeType name="language" dt:type="string" />
<AttributeType name="processorArchitecture" dt:type="string" />
<AttributeType name="version" dt:type="string" />
<AttributeType name="optional" dt:type="enumeration" dt:values="yes no" />
<AttributeType name="clsid" dt:type="string" />
<AttributeType name="description" dt:type="string" />
<AttributeType name="threadingModel" dt:type="string" />
<AttributeType name="tlbid" dt:type="string" />
<AttributeType name="progid" dt:type="string" />
<AttributeType name="helpdir" dt:type="string" />
<AttributeType name="iid" dt:type="string" />
<AttributeType name="numMethods" dt:type="ui4" />
<AttributeType name="resourceid" dt:type="string" />
<AttributeType name="flags" dt:type="enumeration" dt:values="control hidden restricted hasdiskimage" />
<AttributeType name="loadFrom" dt:type="string" />
<AttributeType name="hashalg" dt:type="enumeration" dt:values="SHA1 SHA MD5 MD4 MD2" />
<AttributeType name="hash" dt:type="bin.hex" />
<AttributeType name="proxyStubClsid32" dt:type="string" />
<AttributeType name="baseInterface" dt:type="string" />
<AttributeType name="versioned" dt:type="enumeration" dt:values="yes no" />
<AttributeType name="oldVersion" dt:type="string" />
<AttributeType name="newVersion" dt:type="string" />
<AttributeType name="size" dt:type="ui8" />
<AttributeType name="runtimeVersion" dt:type="string" />
<!-- Elements
-->
<ElementType name="assembly" order="seq" model="closed" content="eltOnly">
<attribute type="manifestVersion" required="yes" />
<group order="many" minOccurs="0" maxOccurs="*">
<element type="assemblyIdentity" minOccurs="1" maxOccurs="1" />
<element type="noInherit" minOccurs="0" maxOccurs="1" />
<element type="noInheritable" minOccurs="0" maxOccurs="1" />
</group>
<group order="many" minOccurs="0" maxOccurs="*">
<element type="description" minOccurs="0" maxOccurs="1" />
<element type="noInherit" minOccurs="0" maxOccurs="1" />
<element type="noInheritable" minOccurs="0" maxOccurs="1" />
<element type="comInterfaceExternalProxyStub" minOccurs="0" />
<element type="dependency" minOccurs="0" />
<element type="file" minOccurs="0" />
<element type="clrClass" minOccurs="0" />
<element type="clrSurrogate" minOccurs="0" />
</group>
</ElementType>
<ElementType name="clrClass" model="closed" content="eltOnly">
<attribute type="name" required="yes" />
<attribute type="clsid" required="yes" />
<attribute type="progid" required="no" />
<attribute type="tlbid" required="no" />
<attribute type="description" required="no" />
<attribute type="runtimeVersion" required="no" />
<attribute type="threadingModel" required="no" />
<element type="progid" minOccurs="0" maxOccurs="*" />
</ElementType>
<ElementType name="clrSurrogate" model="closed" content="empty">
<attribute type="clsid" required="yes" />
<attribute type="name" required="yes" />
<attribute type="runtimeVersion" required="no" />
</ElementType>
<ElementType name="assemblyIdentity" model="closed">
<attribute type="name" required="yes" />
<attribute type="version" required="no" />
<attribute type="type" required="no" />
<attribute type="processorArchitecture" required="no" />
<attribute type="publicKeyToken" required="no" />
<attribute type="language" required="no" />
</ElementType>
<ElementType name="comInterfaceProxyStub" model="closed">
<attribute type="iid" required="yes" />
<attribute type="name" required="yes" />
<attribute type="tlbid" required="no" />
<attribute type="numMethods" required="no" />
<attribute type="proxyStubClsid32" required="no" />
<attribute type="baseInterface" required="no" />
</ElementType>
<ElementType name="description" />
<ElementType name="dependency" model="closed" content="eltOnly">
<element type="dependentAssembly" minOccurs="0" maxOccurs="1" />
<attribute type="optional" required="no" />
</ElementType>
<ElementType name="dependentAssembly" model="closed" content="eltOnly">
<element type="assemblyIdentity" minOccurs="1" maxOccurs="1" />
<element type="bindingRedirect" minOccurs="0" maxOccurs="*" />
</ElementType>
<ElementType name="bindingRedirect" model="closed" content="empty">
<attribute type="oldVersion" required="yes" />
<attribute type="newVersion" required="yes" />
</ElementType>
<ElementType name="file" model="closed" content="eltOnly">
<attribute type="name" required="yes" />
<attribute type="hash" required="no" />
<attribute type="hashalg" required="no" />
<attribute type="loadFrom" required="no" />
<attribute type="size" required="no" />
<group order="many" minOccurs="0" maxOccurs="*">
<element type="comClass" minOccurs="0" />
<element type="comInterfaceProxyStub" minOccurs="0" />
<element type="typelib" minOccurs="0" />
<element type="windowClass" minOccurs="0" />
</group>
</ElementType>
<ElementType name="comClass" model="closed" content="eltOnly">
<attribute type="clsid" required="yes" />
<attribute type="threadingModel" required="no" />
<attribute type="progid" required="no" />
<attribute type="tlbid" required="no" />
<attribute type="description" required="no" />
<element type="progid" minOccurs="0" maxOccurs="*" />
</ElementType>
<ElementType name="comInterfaceExternalProxyStub" model="closed" content="empty">
<attribute type="iid" required="yes" />
<attribute type="name" required="yes" />
<attribute type="tlbid" required="no" />
<attribute type="numMethods" required="no" />
<attribute type="proxyStubClsid32" required="no" />
<attribute type="baseInterface" required="no" />
</ElementType>
<ElementType name="typelib" model="closed" content="empty">
<attribute type="tlbid" required="yes" />
<attribute type="version" required="yes" />
<attribute type="helpdir" required="yes" />
<attribute type="resourceid" required="no" />
<attribute type="flags" required="no" />
</ElementType>
<ElementType name="windowClass" model="closed" content="textOnly">
<attribute type="versioned" required="no" />
</ElementType>
<ElementType name="noInherit" model="closed" content="empty" />
<ElementType name="noInheritable" model="closed" content="empty" />
<ElementType name="progid" />
</Schema>
2006年11月29日
摘要: //
FtpManager.h: interface for the CFtpManager class.
////
////////////////////////////////////////////////////////////////////
#
if
...
阅读全文
2006年11月17日
今天从CSDN看见有人问如何从 http://community.csdn.net/Expert/TopicView1.asp?id=5164878 提问从打开的文件句柄获得文件的路径,下面是解决的办法:
#include
<
Psapi.h
>
#define BUFSIZE
512
#pragma comment(lib,
"
Psapi.lib
"
)
BOOL __stdcall GetFileNameFromHandle(HANDLE hFile, LPWSTR lpFileName, DWORD dwSize)
{
BOOL bSuccess
=
FALSE;
WCHAR pszFilename[MAX_PATH
+
1
];
HANDLE hFileMap;
DWORD dwFileSizeHi
=
0
;
DWORD dwFileSizeLo
=
::GetFileSize(hFile,
&
dwFileSizeHi);
if
( dwFileSizeLo
==
0
&&
dwFileSizeHi
==
0
)
{
return
bSuccess;
}
hFileMap
=
::CreateFileMappingW(hFile,
NULL,
PAGE_READONLY,
0
,
1
,
NULL);
if
(hFileMap)
{
void
*
pMem
=
::MapViewOfFile(hFileMap, FILE_MAP_READ,
0
,
0
,
1
);
if
(pMem)
{
if
(::GetMappedFileNameW(GetCurrentProcess(),
pMem,
pszFilename,
MAX_PATH))
{
WCHAR szTemp[BUFSIZE];
szTemp[
0
]
=
L'\
0
';
if
(::GetLogicalDriveStringsW(BUFSIZE
-
1
, szTemp))
{
WCHAR szName[MAX_PATH];
WCHAR szDrive[
3
]
=
L
"
:
"
;
BOOL bFound
=
FALSE;
WCHAR
*
p
=
szTemp;
do
{
*
szDrive
=
*
p;
if
(::QueryDosDeviceW(szDrive, szName, BUFSIZE))
{
UINT uNameLen
=
lstrlenW(szName);
if
(uNameLen
<
MAX_PATH)
{
bFound
=
::_wcsnicmp(pszFilename, szName,
uNameLen)
==
0
;
if
(bFound)
{
WCHAR szTempFile[MAX_PATH];
::wsprintfW(szTempFile,
L
"
%s%s
"
,
szDrive,
pszFilename
+
uNameLen);
::lstrcpynW(pszFilename, szTempFile, MAX_PATH);
}
}
}
while
(
*
p
++
);
}
while
(
!
bFound
&&
*
p);
}
}
::UnmapViewOfFile(pMem);
}
::CloseHandle(hFileMap);
}
if
(lpFileName)
{
::lstrcpynW(lpFileName,pszFilename,dwSize);
bSuccess
=
TRUE;
}
return
(bSuccess);
}
2006年10月27日
今天本座再次站到这里冒着被兄弟们臭鸡蛋淹没的风险,开始胡说八道。现在讲如何包装(界面编程)。不可否认现在的人先看相貌在看功能,所以我们不能不粗略了解一下界面编程。
大概流程是这个样子的:
获取 显示设备内容句柄(HDC)---> 设置输出对象和格式(SelectObject) ---> 画图 --->关闭HDC句柄
举个简单的例子:
LRESULT APIENTRY WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
PAINTSTRUCT ps = {0};
HDC hdc = NULL;
switch (message)
{
case WM_PAINT:
hdc = BeginPaint(hwnd, &ps);
TextOut(hdc, 0, 0, "Hello, Windows!", 15);
EndPaint(hwnd, &ps);
return 0L;
// Process other messages.
}
}
实际上界面编程的内容太多,也太繁琐,最好去下个源码,然后自己写个程序才容易记住。
推荐去
http://www.vckbase.com/ 看看,那里有不少文章和源码可以借鉴和学习。
当然,Windows输入输出处理也属于界面处理的一部分。比如获取和计算鼠标的系列函数。模拟键盘、鼠标输出的函数,临时锁定键盘和鼠标的函数,限定鼠标活动区域的函数等等。
2006年10月12日
嗯,嗯。我来了,怎么在座的都没表示一下,虽然我们圣门不讲究,但是这也太夸张了吧。(我闪~,小样的这样准头的扔砖头也能砸着本座才怪。话音未落某人就被一块巨石压没影了。砖头不行,巨石不就OK了,路人甲阴笑。)
Windows系统的基石之一:文件系统,甚至Windows注册表实际也是建立在文件系统的基础上。你说既然有之一就有之二?正确,之二就是:内存管理系统。什么?你说既然有之二就有之三?没错,之三就是线程管理系统。什么?你说既然有之三就有之四?靠,还有完没完,一边休息去。
下面我们先来看看Windows的文件系统。Windows的文件发展史我就不说了,目前也就FAT32和NTFS比较有名了。FAT32没什么好说,比较简单。NTFS就复杂了不少,包括基于NTFS的EFS、数据流和安全属性。而我们在上层调用API即可,中层的要发送IRP,底层则要调用中断了。有兴趣的可以去查找相应的资料。
简单的说我们只要能读写修改文件就好了。
C / C++中的文件操作 :
C 中的 fopen、fread、fwrite、fseek、ftell、fclose等f系列函数(当然还包含好用的fprintf和fscanf函数)
C++ 中的 fstream系列
基于Windows的文件操作(当然要了解更详细的用法查MSDN去吧,嘎嘎~)
普通操作:
CreateFile、ReadFile、WriteFile、CloseHandle 几个函数
映射操作:
CreateFile、CreateFileMapping、MapViewOfFile、UnmapViewOfFile、CloseHandle几个函数
文件查找操作:
FindFirstFile(Ex)、FindNextFile、FindClose几个函数
文件其他操作:
GetFileSize(Ex)、GetFileType 、FlushFileBuffers、LockFile(Ex)、UnlockFile(Ex)等
整个文件操作:
CopyFile(Ex)、MoveFile(Ex)、DeleteFile、SHFileOperation等
接着我们来谈谈Windows注册表吧。什么是注册表?在本座看来注册表就是记录系统设定和用户设定的数据库。那么我们怎么来操作注册表呢?
别急,Windows为我们准备好了一系列API函数呢。
操作注册表流程:
打开路径(RegOpenKey[Ex]),保存打开的句柄。(RegConnectRegistry 可以替代它打开远程注册表)
操作句柄(RegQueryValue读取值,RegSetValue写值,RegEnumKey枚举值)
操作完成后,关闭句柄。(RegCloseKey)
Ring3下监视注册表特定值:
RegNotifyChangeKeyValue (例程及说明见MSDN)
读写ini文件的API(为了兼容以前的分类M$分类该系列为注册表操作)
GetPrivateProfile系列读取Ini文件函数(例GetPrivateProfileInt函数)
WritePrivateProfile系列写Ini文件函数
啊?!什么时候人都跑光了?晕,那我还讲啥。回家卖地瓜去(嘘~,不要告诉别人,没办法,最近经济不景气啊)
2006年10月8日
将消息放到消息队列里有几种方式?知道“茴”字有几个写法吗?记不起来了,去问孔乙己吧。(某人大吼一声:让我来告诉你)
一、将消息放入线程的消息队列。
BOOL PostThreadMessage(DWORD idThread,UINT Msg,WPARAM wParam,LPARAM lParam);
二、广播消息
long BroadcastSystemMessage(DWORD dwFlags,LPDWORD lpdwRecipients,UINT uiMessage,WPARAM wParam,LPARAM lParam);
//当然BroadcastSystemMessageEx函数也能达到同样的效果
三、通知指定的窗口
BOOL PostMessage(HWND hWnd,UINT Msg,WPARAM wParam,LPARAM lParam);
LRESULT SendMessage(HWND hWnd,UINT Msg,WPARAM wParam,LPARAM lParam);
BOOL SendNotifyMessage(HWND hWnd,UINT Msg,WPARAM wParam,LPARAM lParam);
//它们可以在hWnd使用HWND_BROADCAST值,表示广播给当前桌面的顶层窗口
//另外仔细考虑一下他们有什么区别?
四、有超时限制的消息通知
LRESULT SendMessageTimeout(HWND hWnd,UINT Msg,WPARAM wParam,LPARAM lParam,UINT fuFlags,UINT uTimeout,PDWORD_PTR lpdwResult);
考虑一下,为什么Windows提供了这么多种相似的消息通知函数,他们各用在什么样的场合?答案在MSDN中都能找到只要你仔细看的话。
如果你要仔细了解其他的消息对列处理函数的话,不妨仔细看看核心编程的26章。因为消息的内容实在是太多了,这是Windows系统用户界面交互的最重要的方式之一,一定要吃透才好哦。
2006年9月29日
嗯,本座又来了(咦?为什么说又?)。谁炼了本座推荐的《葵花宝典》[《Windows 核心编程》]的举手。我数数,0,……真是失望啊,一个都没有,还是有人偷偷练了却不说(嘿嘿,某人奸笑中)。
算了,开始讲讲Windows消息。我们知道Windows的用户界面是由消息驱动的,比如你点击了某个按钮,那么这个按钮的主窗口将接收到一个鼠标消息,然后将鼠标消息翻译成按钮单击消息。
那么我们怎么知道在哪里处理这些消息呢?不要急,听我慢慢来吹(住手,说好不打脸的……)。
通常每一个句柄都属于某个窗口注册类,我们用VC的工具Spy++就可以看见,在该类的注册信息里有一个该类的默认处理过程。在RegisterClass 的传入参数里描述的很清楚的。
ATOM RegisterClass( CONST WNDCLASS
*
lpWndClass);
typedef struct {
UINT style;
WNDPROC lpfnWndProc;
//
这里就是默认注册的类处理过程
int
cbClsExtra;
int
cbWndExtra;
HINSTANCE hInstance;
HICON hIcon;
HCURSOR hCursor;
HBRUSH hbrBackground;
LPCTSTR lpszMenuName;
LPCTSTR lpszClassName;
} WNDCLASS,
*
PWNDCLASS;
但是很多时候,我们要的是自己处理该类的动作,比如Button类,我们要自己绘制它的样子,就像开始菜单按钮。
我们在Spy++里可以看见开始菜单按钮的处理过程后面有个描述Subclassed(中文译:子类化)。通常是我们用自己的处理过程替换了默认的处理过程。通常我们用SetWindowLong来改变处理过程。
m_lpfnOldWndProc = (WNDPROC) SetWindowLong(pThis->m_hAttachWnd,GWL_WNDPROC,(LONG)NewDefaultProc);
我们先来看看一个默认的SDK是怎样建立窗口的。
#include <windows.h>
// Global variable
HINSTANCE hinst;
// Function prototypes.
int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int);
InitApplication(HINSTANCE);
InitInstance(HINSTANCE, int);
LRESULT CALLBACK MainWndProc(HWND, UINT, WPARAM, LPARAM);
// Application entry point.
int WINAPI WinMain(HINSTANCE hinstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
MSG msg;
//注册窗口类
if (!InitApplication(hinstance))
return FALSE;
//创建窗口
if (!InitInstance(hinstance, nCmdShow))
return FALSE;
BOOL fGotMessage;
while ((fGotMessage = GetMessage(&msg, (HWND) NULL, 0, 0)) != 0 && fGotMessage != -1)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
UNREFERENCED_PARAMETER(lpCmdLine);
}
BOOL InitApplication(HINSTANCE hinstance)
{
WNDCLASSEX wcx;
// Fill in the window class structure with parameters
// that describe the main window.
wcx.cbSize = sizeof(wcx); // size of structure
wcx.style = CS_HREDRAW |
CS_VREDRAW; // redraw if size changes
wcx.lpfnWndProc = MainWndProc; // points to window procedure
wcx.cbClsExtra = 0; // no extra class memory
wcx.cbWndExtra = 0; // no extra window memory
wcx.hInstance = hinstance; // handle to instance
wcx.hIcon = LoadIcon(NULL,
IDI_APPLICATION); // predefined app. icon
wcx.hCursor = LoadCursor(NULL,
IDC_ARROW); // predefined arrow
wcx.hbrBackground = GetStockObject(
WHITE_BRUSH); // white background brush
wcx.lpszMenuName = "MainMenu"; // name of menu resource
wcx.lpszClassName = "MainWClass"; // name of window class
wcx.hIconSm = LoadImage(hinstance, // small class icon
MAKEINTRESOURCE(5),
IMAGE_ICON,
GetSystemMetrics(SM_CXSMICON),
GetSystemMetrics(SM_CYSMICON),
LR_DEFAULTCOLOR);
// Register the window class.
return RegisterClassEx(&wcx);
}
BOOL InitInstance(HINSTANCE hinstance, int nCmdShow)
{
HWND hwnd;
// Save the application-instance handle.
hinst = hinstance;
// Create the main window.
hwnd = CreateWindow(
"MainWClass", // name of window class
"Sample", // title-bar string
WS_OVERLAPPEDWINDOW, // top-level window
CW_USEDEFAULT, // default horizontal position
CW_USEDEFAULT, // default vertical position
CW_USEDEFAULT, // default width
CW_USEDEFAULT, // default height
(HWND) NULL, // no owner window
(HMENU) NULL, // use class menu
hinstance, // handle to application instance
(LPVOID) NULL); // no window-creation data
if (!hwnd)
return FALSE;
// Show the window and send a WM_PAINT message to the window
// procedure.
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
return TRUE;
}
LRESULT CALLBACK MainWndProc(
HWND hwnd, // handle to window
UINT uMsg, // message identifier
WPARAM wParam, // first message parameter
LPARAM lParam) // second message parameter
{
//这里响应窗口消息
switch (uMsg)
{
case WM_CREATE:
// Initialize the window.
return 0;
case WM_PAINT:
// Paint the window's client area.
return 0;
case WM_SIZE:
// Set the size and position of the window.
return 0;
case WM_DESTROY:
// Clean up window-specific data objects.
return 0;
//
// Process other messages.
//
default:
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
return 0;
}
我们看到通常建立了窗口后,还要建立消息循环才能响应消息。
我们来总结一下如何创建窗口的几中方式(对话框是一种特殊的窗口):
使用Windows默认提供的类创建窗口(CreateWindow[Ex]、CreateDialog[Ex]等)
定义处理过程的窗口(RegisterClass后再CreateWindow)
子类化处理窗口(CreateWindow后SubClassWindow)
int WINAPI WinMain(HINSTANCE hinstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
MSG msg;
if (!InitApplication(hinstance))
return FALSE;
if (!InitInstance(hinstance, nCmdShow))
return FALSE;
//这里建立消息循环
BOOL fGotMessage;
while ((fGotMessage = GetMessage(&msg, (HWND) NULL, 0, 0)) != 0 && fGotMessage != -1)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
这样窗口就能响应消息了,可以等待Windows的消息通知,我们的消息通知,和其他用户的消息通知。至于怎么通知下次再说喽。(某人从背后抽出一把剑,然后大喝一声:御剑飞仙,然后往下一跳。不一会儿传来凄厉的惨叫~ 。小朋友切勿模仿)
2006年9月15日
今天天气不错,是本座开坛做法,哦,是讲课。本来按道理来说今天应该讲剑法了。不过之前还是有必要考验一下。你,你,还有你出列。(军训?)回答几个简单问题:
* 和 & 的异同:void Sum(int *piInout);和void Sum(int &piInout);
解释 |和||,&和&&,=和==
2 << 2 ; 和 cout << 2;
int I = 0; int t = ++I; 和 int I = 0; int t = I++;
const char *pcCont = “Hello”; 和 char * const pcCont = “Hello”的异同
inline 和 宏函数的异同
解释类public、protected、private的继承的区别
几种类型转化的方式,以及优缺点。
解释函数的覆盖、隐藏和重载
全局变量的隐藏和访问,局部变量的全局生存?
什么是断言?其原理是什么?
宏函数的陷阱在哪里?
实现自己的自动内存指针模版(允许手工释放内存或者超出生存期自动释放内存)
RTTI以及其优缺点?
什么,你说不知道,那你还在这站着?回去看书,什么时候明白什么时候再过来。你问我答案?切,自己上网去查Google,百度随便用。(某人偷偷擦了擦头上的汗,松了口气,幸亏我脑筋转得快,要不还不被整得脑震荡,我得意的笑~。接着就被不知道从哪里飞来的西红柿&&鸡蛋给淹没了)
(虽然,一身狼狈,但是总算爬出来了。呼~活过来的感觉真好)上回本座讲到我们圣门入门快速,但是容易走火入魔,怎么办?不用怕,要做圣门弟子就要修习医道(Debug),在走火入魔的时候就可以又活过来了,直到以后有经验了,就知道怎么预防了。本门的医术分为:望闻问切诊。望术(TRACE和LOG)、闻术(Release调试)、问术(源码级调试)、切术(逆向分析)、诊术(其他Debug辅助工具,如代码检查工具
PC-Lint等),博大精深,甚至本座也不过是初通皮毛而已。
(我闪,某人灵活的躲过飞来的砖头)别急,马上讲,我错了还不行么。Windows下面进行编程就不能不讲Windows的消息和事件。我们知道Windows和Dos最大的构架上的区别是,Windows采用的是消息驱动用户的方式。当某件事情发生的时候,Windows就将消息通知给用户窗口,让不同的窗口可以有不同的行为。
通常Windows有三种方式响应模式:
中断,最基本的响应方式,通常在内核中处理,包括硬中断和软中断 (表现为 汇编中的 int xx)
事件,Windows系统中最普遍的通知的方式
消息,Windows用于用户资源的线程最常用的响应方式
下面就推荐大家一本传说中的葵花宝典。
翻开第一页跟我念:欲练神功,挥刀自宫!
翻开第二页跟我念:若不自宫,亦可成功!
翻开第三页跟我念:即使自宫,未必成功!
(人呢?地上有一插满刀的人形物体……)
《Windows 核心编程》确实是一本不错的书,网上到处都有下载不妨好好看看。由于开坛做法的某人失踪中,所以今天就到这。
2006年9月13日
本座回来啦。哈哈……。今天就开始入门训练了。
虽然本门对入门内功的要要求很低,但是一点内功都没有的居然也敢来?看什么看,说得就是你,先回去学一个星期的C++语法结构再回来。不用犹豫,本座会为你留好位置的,阿门。(汗~,这是什么语气,扁他,只见一群人围上把那个身着黑衣的自称‘本座’的人一阵暴踩)
(只见某人理了理衣裳,似乎什么事都没有发生的样子。)
恩,你说不知道该怎么学,看在XXX的面子上就告诉你了,听好了,只说一遍。累的时候可以当枕头,怒的时候可以当板砖,失眠时可以让你眼皮打架,没错这就是《C++ Primer》,居家旅行、杀人放火、修身养性的必备良药。
什么!拿在手里不知道该怎么办?还能怎么办,把它吃下去,消化它,就能增加n年内力。基本内功就那么几个要求:
1 掌握C++关键字
数据定义关键字(bool、int、short、long、float、unsigned、typedef、struct、class等)
操作符关键字(+、-、|、*、&、/、%、++、--、+=、>等)
逻辑比较关键字(&&、||、==等)
流程控制关键字(if、while、goto等)
异常处理关键字(try、catch等)
编译预处理关键字(#include、#define、#pragma等)
2 掌握C++语法
数据生存期(局部、全局、静态、外部、寄存器等)
运算优先级
命名空间和域
类的继承规则(public、protected、private等)
函数的覆盖、隐藏、重载以及函数指针
* 模版和泛型算法
* 运行时刻类型识别(RTTI)
现在合上书,能对上面进行补充和解释的话那么入门内功就够了,至于什么对象设计原则之流的以后再说,毕竟我们是圣门,不是白道那群……(话音刚落,只见一群人围上把某人乱扁)
(到众人散去后,留下了奄奄一息的某人)不行了,看来今天是不撑了。同志们我胡汉三还会回来的。
2006年9月8日
开始之前先了解一下本人,哦不,本座什么身份。本座是魔门,哦不,圣门中流传至今5年的“叫天天不应,叫地地不灵”流派的唯一仅存长老级人物(汗~,不是长老也不是掌门,混得真够呛),号称“吾本无用”是也。
所以,白道人士就不能看本座的秘籍,否则走火入魔后,管杀不管埋,嘿嘿。
先解释一下武学分类(本门内部使用,若乱用后果自负)。
1. 内功:本门指的是 C++语言基础 (如果换成其他语言基础,就不是本流派了) 。本流派内功号称“道家小无相功”可以模拟天下一切内功心法,虽然效果打点折扣(介绍见《天龙八部》)
2.外功: 本门指的是 辅助解决问题的手段即查找资料。
3.剑法: 本门指的是 Windows下面的编程知识。炼刀法(Linux、Unix下)的仁兄可以闪了。
4.剑: 本门指的是 VC。用枪(VB)、戟(Delphi)等友人可以适当观摩,出了问题本座不负任何责任。
白道人士的修炼方法是从内而外,而我们圣门的方式是从外而内。本门心法入门迅速,快捷,但是容易走火入魔(程序容易出现Bug),意志不坚定者、无怀疑精神者赶紧闪开。白道的修炼方式虽然不易走火入魔,但是像苦行僧一样枯燥无味,而且甚是耗时。这种一步一个脚印,僵化的白道方式比较适合慢热型的江湖人士。
本座在下一篇继续按圣门的“叫天天不应,叫地地不灵”流派修炼讲解。
[注:本文以武侠为背景希望能够去除枯燥的教学方式给人以比较深刻的印象,但是某些比喻可能不当,一笑而过即可。]