2007年11月9日
Sub AddDeleteRemark()
Dim CommentHeader As String
Dim ResultText As String
Dim CommentPreString As String
Dim CommentEnd As String
Dim dateString As String
Dim strInputComment As String
Dim timeGet As Date
Dim ts As TextSelection = DTE.ActiveWindow.Selection()
Dim start As EditPoint = ts.TopPoint.CreateEditPoint()
Dim endpoint As EditPoint = ts.BottomPoint.CreateEditPoint()
Dim endpt As TextPoint = ts.BottomPoint
timeGet = Now
dateString = timeGet.Year & "-" & timeGet.Month & "-" & timeGet.Day & " " & timeGet.ToShortTimeString
strInputComment = InputBox("What is your comment?", "Input Delete Remark Text", " ")
If strInputComment.Length = 0 Then
Exit Sub
End If
Dim commentStart As String = Utilities.LineOrientedCommentStart()
commentStart = commentStart & vbTab
CommentPreString = "//===============Delete By Ditans.King For "
strInputComment = strInputComment.Trim()
If strInputComment.Length = 0 Then
Dim strTextStartLine As String
Dim strTextCurLine As String
Dim strTextEndLine As String
DTE.UndoContext.Open("Comment Region")
Try
start.StartOfLine()
strTextStartLine = start.GetText(start.LineLength)
If strTextStartLine.StartsWith(CommentPreString) Then
If endpoint.LineLength = 0 Or endpoint.AtStartOfLine Then
endpoint.LineUp()
End If
endpoint.StartOfLine()
strTextEndLine = endpoint.GetText(endpoint.LineLength)
If strTextEndLine.StartsWith(CommentPreString) Then
endpoint.Delete(endpoint.LineLength)
start.Delete(start.LineLength)
start.StartOfLine()
Do While (start.LessThan(endpt))
strTextCurLine = start.GetText(start.LineLength)
If strTextCurLine.StartsWith(commentStart) Then
start.Delete(commentStart.Length)
End If
start.LineDown()
start.StartOfLine()
Loop
End If
End If
Finally
DTE.UndoContext.Close()
End Try
Exit Sub
Else
Dim strTextStartLine As String
Dim strTextEndLine As String
Dim strPreEndLineDown, strEndLineDown As String
Dim bRemark As Boolean = False
CommentHeader = CommentPreString & strInputComment & "===============//Begin-> " & dateString & vbLf
CommentEnd = CommentPreString & strInputComment & "===============//End <- " & dateString
strPreEndLineDown = vbLf
strEndLineDown = vbLf
DTE.UndoContext.Open("Comment Region")
Try
start.StartOfLine()
strTextStartLine = start.GetText(start.LineLength)
If strTextStartLine.StartsWith(CommentPreString) Then
If endpoint.LineLength = 0 Or endpoint.AtStartOfLine Then
endpoint.LineUp()
strEndLineDown = ""
End If
endpoint.StartOfLine()
strTextEndLine = endpoint.GetText(endpoint.LineLength)
If strTextEndLine.StartsWith(CommentPreString) Then
endpoint.Delete(endpoint.LineLength)
start.Delete(start.LineLength + 1)
strPreEndLineDown = ""
bRemark = True
End If
End If
If endpoint.LineLength = 0 Or endpoint.AtStartOfLine Then
strPreEndLineDown = ""
End If
CommentEnd = strPreEndLineDown & CommentEnd & strEndLineDown
start.StartOfLine()
start.Insert(CommentHeader)
If Not bRemark Then
Do While (start.LessThan(endpt))
start.Insert(commentStart)
start.LineDown()
start.StartOfLine()
Loop
End If
endpoint.Insert(CommentEnd)
Finally
DTE.UndoContext.Close()
End Try
End If
End Sub
Sub AddModifyRemark()
Dim CommentHeader As String
Dim ResultText As String
Dim CommentEnd As String
Dim dateString As String
Dim CommentPreString As String
Dim strInputComment As String
Dim timeGet As Date
Dim ts As TextSelection = DTE.ActiveWindow.Selection()
Dim start As EditPoint = ts.TopPoint.CreateEditPoint()
Dim endpoint As EditPoint = ts.BottomPoint.CreateEditPoint()
Dim endpt As TextPoint = ts.BottomPoint
timeGet = Now
' dateString = timeGet.ToLongDateString & " " & timeGet.ToShortTimeString
' dateString = timeGet.ToLocalTime & " " & timeGet.ToShortTimeString
' dateString = timeGet.ToFileTime & " " & timeGet.ToShortTimeString
dateString = timeGet.Year & "-" & timeGet.Month & "-" & timeGet.Day & " " & timeGet.ToShortTimeString
strInputComment = InputBox("What is your comment?", "Input Modify Remark Text", " ")
If strInputComment.Length = 0 Then
Exit Sub
End If
CommentPreString = "//===============Modify By Ditans.King For "
strInputComment = strInputComment.Trim()
CommentHeader = CommentPreString & strInputComment & "===============//Begin-> " & dateString & vbLf
CommentEnd = CommentPreString & strInputComment & "===============//End <- " & dateString
DTE.UndoContext.Open("Comment Region")
Try
Dim strTextStartLine As String
Dim strTextEndLine As String
Dim strPreEndLineDown, strEndLineDown As String
strPreEndLineDown = vbLf
strEndLineDown = vbLf
start.StartOfLine()
strTextStartLine = start.GetText(start.LineLength)
If strTextStartLine.StartsWith(CommentPreString) Then
If endpoint.LineLength = 0 Then
endpoint.LineUp()
strEndLineDown = ""
End If
endpoint.StartOfLine()
strTextEndLine = endpoint.GetText(endpoint.LineLength)
If strTextEndLine.StartsWith(CommentPreString) Then
endpoint.Delete(endpoint.LineLength)
start.Delete(start.LineLength + 1)
strPreEndLineDown = ""
End If
End If
If endpoint.LineLength = 0 Or endpoint.AtStartOfLine Then
strPreEndLineDown = ""
End If
CommentEnd = strPreEndLineDown & CommentEnd & strEndLineDown
start.StartOfLine()
start.Insert(CommentHeader)
endpoint.Insert(CommentEnd)
Finally
DTE.UndoContext.Close()
End Try
End Sub
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 =