12/27/2005

Jiangsheng的CSDN Digest (Oct 2005)

CSDN 讨论总结系列:



在default桌面中如何获取Winlogon桌面位图(VC/MFC 进程/线程/DLL )




为何我的服务程序只能获取default的桌面位图,但不能获取Winlogon桌面的?怎么才能做到象DameWare Mini Remote Control那样既可获取default的桌面位图,也支持Winlogon下的位图?




使用
HDESK OpenDesktop(
LPTSTR lpszDesktop, // name of the desktop to open
DWORD dwFlags, // flags to control interaction with other applications
BOOL fInherit, // specifies whether returned handle is inheritable
DWORD dwDesiredAccess // specifies access of returned handle
);

BOOL SetThreadDesktop(
HDESK hDesktop // handle to the desktop to assign to this thread
);
 


讲下window station 和desktop。它们主要是用于服务程序,一般的应用程序不必使用它们。它们可以用来对服务进行保护。运行在不同的window station 或不同的desktop下的应用程序,不能互相发送消息、挂钩、使用同一个clipboard等等。主要是出于安全的目的。


服务程序一般使用的是LocalSystem帐户,拥有自己的window station,和Default桌面,这个window station是不能于用户交互的,也就是说,你不能在上面显示窗口,它也不接受用户的鼠标、键盘等输入。

使用用户帐户登录以后,看到的桌面,是WinSta0(window station)下的Default(desktop).
WinSta0下有3个桌面:
WinLogon :以Logon对话框的形式出现.当用户登录以后,WinLogon.exe切换到Default desktop.
Default :这是Explorer.exe和所有用户程序窗口出现的地方,也就是我们通常使用windows看见的地方.应用程序就运行在这个桌面上
Screen saver :系统空闲的时候,运行屏保的桌面.

当在“计算机管理”中选择一个服务,修改属性,选择“登录”标签页的“允许服务与桌面交互”,那么该服务就使用的是WinSta0(window station)下的Default(desktop). 也就可以与服务进行交互操作了。这时,能获取default的桌面位图,因为线程的桌面就是WinSta0下的Default。要想同时获得Winlogon桌面位图,应该先把线程的桌面设置成Winlogon。



OpenInputDesktop返回就是当前活动桌面
基于对话框的程序的时候,是因为你的权限不够,所以在winlogon下会返回空。利用返回值为空的方法不适合服务。
使用的是系统权限(运行在服务下),当程序切换到winlogon前,先用OpenInputDesktop得到当前桌面,再用GetUserObjectInformation就可以得到当前的桌面的名字,是default。切换后,再用同样的方法得到的是winlogon。再切换回来,得到的是default。

说个小插曲,第一次做的时候,只切换到winlogon,程序没有自动切换回default。只好重新启动。




连接时报某个接口ID未定义的问题 (VC/MFC ATL/ActiveX/COM)




Linking...
MainFrm.obj : error LNK2001: unresolved external symbol _IID_IExtractImage
Debug/DVBTools.exe : fatal error LNK1120: 1 unresolved externals
Error executing link.exe.

但我的头文件定义了,也包含了下面的定义
//BB2E617C-0920-11d1-9A0B-00C04FC2D6C1
DEFINE_GUID(IID_IExtractImage,
0xBB2E617C, 0x0920, 0x11d1, 0x9A, 0x0B, 0x00, 0xC0, 0x4F, 0xC2, 0xD6, 0xC1);




在没有包含Initguid.h的地方,DEFINE_GUID宏创建外部引用来使用GUID值,在包含Initguid.h的地方,DEFINE_GUID重定义DEFINE_GUID宏以产生GUID的定义。
如是没有在任何地方添加Initguid.h,会得到一个链接错误:"unresolved external symbol." ,如果同样的GUID包含Initguid.h两次,会得到编译错误"redefinition; multiple initialization."要解决这些问题,请确认Initguid.h只包含一次。同样的,不要包含Initguid.h到预编译头文件中去,因为预编译头文件会被每个源文件包含。




我怎么样将自己定义VIEW,比如我自己做了一个可以改变单行颜色的clistctrl我想在view里面使用此功能(VC/MFC 界面)




我要做一个列表视Listview,但系统默认的CListView类没有单行改变颜色的功能,只能自己做一个新

视,新视图从CView继承。请问我接下来怎么用自定义的Clistctrl来填充视口啊?




如果你的CListCtrl扩展类没有增加成员变量或者虚函数(这似乎是一种缚手缚脚的扩展),那么你可以直接把任何窗口类类型为SysListView32的CWnd对象指针直接转化为你的CListCtrl扩展类指针使用。

如果你的CListCtrl扩展类在CListCtrl的基础上增加了成员变量或者虚函数,那么推荐用基于CFormView(或者更麻烦一些,CCtrlView)的类来替代基于CListView的实现:在FormView的对话框上放一个列表控件,在FormView大小变化时移动列表控件以充满视图。如果你希望让视图类而不是视图中的控件来处理和响应消息,你需要捕捉控件收到的用户输入消息并通过发送WM_NOTIFY通知转发到视图,以及捕捉视图收到的控制消息并转发到控件。使用这种方法也可以自行封装基于CCtrlView的自定义控件视图类。

如果你的CListCtrl扩展类不依赖于控件的状态——也就是说,由调用者手动初始化而不是自行处理创建消息,那么可以声明一个CListCtrl扩展类对象,之后调用CWnd::Attatch连接到CListView派生类对象来接管窗口过程。

其它的通用控件扩展类也可以使用上述方法移植到CCtrlView派生类。


其他的方法包含:


把Ctrl和View中重复的功能作成模板(可以参考CHTMLEditCtrl/CHTMLEditView的实现)
单独编写Ctrl和View,把Ctrl和View中重复的代码作成辅助函数供窗口的消息相应函数调用。




VC 2003.net的Crt代码里头的memcmp函数 (C/C++ C++ 语言)




其中一段是:

test eax,1
jz short main_loop

mov cl,[esi]
cmp cl,[edi]
jne short not_equal
add esi,1
add edi,1
sub eax,1
jz short done ; eax is already 0

main_loop:
mov cl,[esi]
mov dl,[edi]
cmp cl,dl
jne short not_equal

mov cl,[esi+1]
mov dl,[edi+1]
cmp cl,dl
jne short not_equal

add edi,2
add esi,2

sub eax,2
jnz short main_loop
done:
pop edi
pop esi
retnull:
ret ; _cdecl return

上面的我死活没有想懂,为什么要两个字节一起比较?




前面还有


or edx,edi
and edx,3 ; edx=0 iff buf1 are buf2 are aligned
jz short dwords


只要 dst , src 是 DWORD 对齐的,就一次比较 4 个字节


dwords:
mov ecx,eax
and eax,3 ; eax= counter for tail loop

shr ecx,2
jz short tail_loop_start
; counter was >=4 so may check one dword
rep cmpsd

jz short tail_loop_start
 


看来在不太增加代码复杂度的情况下每两字节可以少执行一次跳转。这部分是在两个缓冲区的起始地址没有对齐的情况下进行的。这样就是为了在性能上的一个折中,如果单个字节比较的话,跳转就太多,浪费CPU时钟,如果设置多余2个字节的比较的话,代码又太过冗长,超出了short的跳转范围,那么选择每两个字节进行比较的话,性能不但有所提升,而且代码也比较紧凑,没有超出short跳转的范围




Com如何导出自定义结构 (VC/MFC ATL/ActiveX/COM)




我想通过com的接口函数输入,输出一个自定义的结构.该结构内部还包含一个自定义的union.我该怎么作.我建立的是atl工程.(vc6.0中的atl).我的struct和别人的不同(我的struct里面不全是简单的数据结构(如int,char....),我的struct里面还包含一个union),那我该怎么办?
那有没有好的方法能解决复合型的struct(就是struct里面,不仅仅只有简单的数据类型(int,char...)还包含其他的复杂结构(struct, union.....))




对于普通的C++接口,任何自定义类型都可以作为接口函数类型,但如果是自动化接口,接口函数的参数必须是OLE变量类型,这时需要把自定义类型通过某种些技巧转化成等价的OLE变量类型,比如直接把结构封装成COM对象,之后传递接口给外部操作。都用COM实现了整个对象,没必要就因为参数的问题导至组件只能被C/C++调用.那也太划不来了
 


参见


http://www.vckbase.com/document/viewdoc/?id=1404
http://community.csdn.net/Expert/topic/3872/3872346.xml?temp=.1874048
 




一个托管的类指针对象,能转化成void*吗(.NET技术 VC.NET)




混合了MFC和.NET framework的程序,一个函数的参数类型是void*,而现在想传给这个函数的变量类型是一个托管类指针,像__gc MyClass*,传不了,也强制转换不了。在不改变函数参数的前提下,有什么办法吗?




A __gc pointer shall not be cast to a __nogc pointer.
A pinning pointer can be implicitly converted to a __nogc pointer.
This is the only mechanism provided for passing addresses in the common language runtime heap to functions expecting __nogc pointers. The primary use for this is passing such addresses to unmanaged functions in external DLLs.




请问如何判断内置浏览器可以通过GoBack()和GoForward()来“后退、前进”? (.NET技术 C# )




我用的是AxSHDocVw.AxWebBrowser
请问那该如何得知是否可以“后退”或者“前进”呢?




ExecCommand之前QueryStatus或者捕获CommandStateChang事件
参考http://msdn.microsoft.com/library/default.asp?url=/workshop/browser/webbrowser/reference/ifaces/iwebbrowser2/goback.asp
 




CDHtmlDialog 的问题(js关闭ie的问题) (VC/MFC 界面 )




我用CDHtmlDialog 来浏览网页
这个网页中有一个按钮,点击次按钮,会掉用js来关闭IE

但我的CDHtmlDialog能不能捕捉到这个事件呢?

因为我的程序中只使用一个CDHtmlDialog来显示网页,当用户关闭这个CDHtmlDialog的时候我实际是让他ShowWindow(SW_HIDE),而不是真正的关闭,在下次用户要显示另一个网页的时候再show出来

当用户点击网页中的关闭按钮后,我想先捕捉到这个“退出”事件,然后隐藏掉我的CDHtmlDialog


可是现在用户点击网页中的退出按钮,我的dlg仍然还在,但这个CDHtmlDialog已经不可以再用了,好像里面的IE控件被关闭了




如果用户的IE是5.5以上版本,捕获DWebBrowserEvents2::WindowClosing事件
如果用户的IE是5.01及以下版本,捕获WM_PARENTNOTIFY消息并且判断消息来源是否是浏览器控件。
OnQuit是IE专用的事件,浏览器控件不会被触发


参见


http://blog.csdn.net/jiangsheng/archive/2003/11/09/3795.aspx





今天看了回调函数发现有个__stdcall与cdecl 非常不解(VC/MFC 硬件/系统 )




调用约定,使用不同的调用约定,则传递参数的顺序和方式会不同,例如多个参数的入栈顺序会不同,而象__fastcall约定会尽可能的使用寄存器传递参数
因此如果一个__stdcall声明的函数通过__cdecl的方式去调用就会出现错误
cdecl是C语言里面函数调用使用得最多的协议(可以说绝大多数都是这个,Unix/Linux下面清一色都是这个……),主要特性是使用eax寄存器保存返回值(通常对于比较小的类型如此),调用方清栈(所以可以支持变参函数),另外它也是C/C++默认的调用协议(也就是说不额外声明的话,默认就是cdecl的)

stdcall是Windows API标准的调用方式,所有的Windows API都是靠这个调用协议,好像一般callback也都是用这个的……


cdecl 参数从右至左入栈,函数负责清除堆栈,返回值的处理如下
VC:
除了浮点数之外的基本类型和大小小于或者等于8字节的结构根据大小不同保存在EAX或者EAX:EDX组合中
浮点数和双精度数保存在fp0中
大小超过8字节的,或者有构造函数、析构函数、虚函数之一的结构或者类在内存中返回。返回值在内存中时调用者会分配对应大小的内存,并且将其作为隐含的第一个参数传递。函数调用之后调用者负责清除这块内存。
其它:
某些编译器在按值传递有析构函数的类和结构时会强制转换成按地址传递。某些编译器会把所有返回值强制放在内存中

stdcall
同cdecl,但是函数调用者负责清除堆栈

thiscall
VC:
同stdcall,但是this指针在ECX中传递,类和结构类型的返回值强制放在内存中。如果函数参数的数目可变,那么同cdecl,但是this指针成为隐含的第一个参数。
其它:
同stdcall,但是this指针成为隐含的第一个参数。

fastcall
除了开始两个大小小于4字节的参数会通过寄存器传递之外,其它同cdecl。

64位平台上调用约定有所变化,但是我没有做过这方面的研究。

参考文章
http://support.microsoft.com/default.aspx/kb/100832
http://p5.club.163.com/viewArticleByWWW.m?boardId=clanguage&articleId=clanguage_104ffea50e53121&boardOffset=0
http://www.codeproject.com/cpp/FastDelegate.asp




求graphics.h的库函数,我的VC没有这个库函数 (C/C++ C语言)




那个库是16位的。
Visual C++1.5以上版本不支持16位的库。如果你要使用这个图形库,可以使用Visual C++ 1.5版,或者使用Borland 的Turbo C++。




ATL的调用(VC/MFC ATL/ActiveX/COM )




假设我在他机用vc 的ATL新建了一个Simple Object,编译了一个dll;

如果我想在本机新的atl工程中 Composite Control中使用这个dll的接口,
通过CoCreateInstance()可以获取得到这个接口,但是前提是这个dll必须在本机注册,
想请问下,如何在调用接口之前,不手动注册他机编译后的dll,而是通过程序来注册这个dll?




调用COM的DllRegisterServer函数,被调用的COM要作为一个DLL的方式来导入DllRegisterServer。就是说用LoadLibrary函数来读取DLL文件然后调用DllRegisterServer。


HINSTANCE hDLL = ::LoadLibrary("*.dll");
typedef BOOL (_stdcall *lpRegHnd)(void);
lpRegHnd regHND;
regHND = (lpRegHnd)::GetProcess( hDLL, "DllRegisterServer");
if (regHND == NULL )
return -1;
regHND(); //register DLL;
::FreeLibrary( hDLL );
或者调用ShellExecute函数调用Regsvr32 来执行注册。


The RegSvr32 utility installs a DLL as an in-process server. It invokes one
or more functions that are implemented by the application, and exported by
name by the DLL. The primary task of these functions is to create or delete
appropriate registry entries. The following functions can be invoked by
RegSvr32.

a.. DllRegisterServer is used for installing DLLs. It should create any
necessary registry keys.
b.. DllUnregisterServer is used for uninstalling DLLs. It should delete
any registry keys that are no longer needed.
c.. DllInstall is used for both installing and uninstalling DLLs. It can
be used in addition to DllRegisterServer and DllUnregisterServer, or in
place of them. It is intended for DLLs that can be installed in more than
one way. Unlike DllRegisterServer and DllUnregisterServer, which take no
arguments, DllInstall takes two arguments. The first is a Boolean value that
specifies whether the DLL is being installed (TRUE) or uninstalled (FALSE).
The second is a string that can be used to specify which installation
procedure to use.
The following is the RegSvr32 command-line syntax.

regsvr32 [flag1 [flag2 ...] DllName
/u
Uninstall the DLL. If the /i flag is not included DllUnregisterServer will
be invoked.
/i:"string"
Invoke DllInstall. If the /u flag is included, DllInstall is instructed to
uninstall the DLL, by setting the first parameter to FALSE. Otherwise, the
first parameter will be set to TRUE, and DllInstall will install the DLL.
The string following the colon will be passed in as the second parameter to
DllInstall. It is used to specify which installation procedure is to be
used. If /i is used without the colon and string literal, the second
parameter of DllInstall will be set to NULL. Unless the /n flag is included,
DllRegisterServer or DllUnregisterServer will also be invoked.
/n
Do not invoke DllRegisterServer or DllUnregisterServer. This flag can only
be used in combination with /i.
/s
Silent.
/c
Console output.
If no flags are specified, RegSvr32 will install the DLL by invoking
DllRegisterServer.

To register a DLL named DllName.Dll by invoking its DllRegisterServer
function, use the following command:

regsvr32 dllname.dllTo unregister the DLL with DllInstall's "uninstall_1"
procedure without also invoking DllUnregister, use the following command:

regsvr32 /u /n /i:"uninstall_1" dllname.dll




程序里使用 ie 控件的问题(VC/MFC 基础类)




我的问题是, ie 包装类可以很好的工作,但是我不知道怎样取得它的 iWebBrowser2 接口
ie包装类是 vc 自动生成的CWebBrowser2:public CWnd.




CWnd::GetControlUnknown之后QueryInterface IID_IWEbBrowser2。注意GetControlUnknown之后不能Release




CHtmlView中的ScrollBar的问题 (VC/MFC 界面 )




当网页内容超过视图范围时,会有ScrollBar显示出来。
现在我如何使ScrollBar不被显示出来




1.通过修改网页 <frame noscroll="noscroll">
2.http://support.microsoft.com/default.aspx?scid=kb;en-us;Q324419
你也可以自定义浏览器控件的容器,实现IDOCHostUIHandler的GetHostInfo方法。在VC7.0中比较简单一些,你可以直接使用CHTMLView和CDHTMLDialog内建的GetHostInfo方法,或者参考这两个类的源代码,在创建控件的时候使用类似于CBrowserControlSite的容器。在VC6中你需要用http://support.microsoft.com/kb/q236312/这样的方法在创建控件的时候使用自定义的容器。
 




插入USB盘的时候电脑会自动弹出一个打开列表的窗口,询问要做什么,请问如何把我自己的程序加到这个列表中,用我的程序打开? (VC/MFC 硬件/系统)




HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Explorer\AutoplayHandlers
http://msdn.microsoft.com/msdnmag/issues/01/11/autoplay/default.aspx
 




在WEB中读取网上领居的机器上的文件报权限不足,请问如何处理??网上邻居的文件已经设了共享且没加密码。 (.NET技术 ASP.NET )




直接通过网上邻居用此形式就能访问是因为当前登录用户有权限
asp.net进程是运行在服务器的aspnet用户下的,如果权限不足,可以让IIS服务和桌面程序交互,之后编一个桌面程序来和ASP.Net中的程序通讯(推荐),或者修改aspnet用户的权限(不推荐,容易造成安全问题)你也可以临时扮演一个有权限的用户角色。


利用角色扮演类,执行这个类以后就是一管理员身份登陆系统后的权限。
用法:
using System;
using System.DirectoryServices;
using System.Runtime.InteropServices;
using System.Security.Principal;
using System.Security.Permissions;


///
/// 用户模拟角色类。实现在程序段内进行用户角色模拟。
///
public class IdentityImpersonation

{

[DllImport("advapi32.dll", SetLastError=true)]

public static extern bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword, int dwLogonType, int dwLogonProvider, ref IntPtr phToken);



[DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)]

public extern static bool DuplicateToken(IntPtr ExistingTokenHandle, int SECURITY_IMPERSONATION_LEVEL, ref IntPtr DuplicateTokenHandle);



[DllImport("kernel32.dll", CharSet=CharSet.Auto)]

public extern static bool CloseHandle(IntPtr handle);



// 要模拟的用户的用户名、密码、域(机器名)

private String _sImperUsername;

private String _sImperPassword;

private String _sImperDomain;

// 记录模拟上下文

private WindowsImpersonationContext _imperContext;

private IntPtr _adminToken;

private IntPtr _dupeToken;

// 是否已停止模拟

private Boolean _bClosed;



///

/// 构造函数

///

/// 所要模拟的用户的用户名

/// 所要模拟的用户的密码

/// 所要模拟的用户所在的域

public IdentityImpersonation(String impersonationUsername, String impersonationPassword, String impersonationDomain)

{

_sImperUsername = impersonationUsername;

_sImperPassword = impersonationPassword;

_sImperDomain = impersonationDomain;



_adminToken = IntPtr.Zero;

_dupeToken = IntPtr.Zero;

_bClosed = true;

}



///

/// 析构函数

///

~IdentityImpersonation()

{

if(!_bClosed)

{

StopImpersonate();

}

}



///

/// 开始身份角色模拟。

///

///

public Boolean BeginImpersonate()

{

Boolean bLogined = LogonUser(_sImperUsername, _sImperDomain, _sImperPassword, 2, 0, ref _adminToken);



if(!bLogined)

{

return false;

}



Boolean bDuped = DuplicateToken(_adminToken, 2, ref _dupeToken);



if(!bDuped)

{

return false;

}



WindowsIdentity fakeId = new WindowsIdentity(_dupeToken);

_imperContext = fakeId.Impersonate();



_bClosed = false;



return true;

}



///

/// 停止身分角色模拟。

///

public void StopImpersonate()

{

_imperContext.Undo();

CloseHandle(_dupeToken);

CloseHandle(_adminToken);

_bClosed = true;

}

}
使用的时候在获取权限的时候这样写:
IdentityImpersonation identityImpersonation = new IdentityImpersonation("administrator",
"yourpassword","yourhostname");
identityImpersonation.BeginImpersonate();//开始管理员扮演
//特殊操作
.....
....
identityImpersonation.StopImpersonate(); //结束扮演
 




在基于CSrollView为基类的程序中,使用CRectTracker(橡皮筋类),在视图出现滚动条时,CRectTracker不能正常显示(VC/MFC 界面 )




我的程序中视图基于CSrollView,并且使用了CRectTracker类(橡皮筋类),在视图中没有出现滚动条时,CRectTracker类(橡皮筋类)显示正常,可以正常的随鼠标移动,扩大,缩小等操作;但是当视图出现滚动条时,当CRectTracker类(橡皮筋类)没有被当前视图所包含时,移动视图滚动条,移动视图时则不能出现CRectTracker,不知道这是什么问题?怎么解决?
void CMonitorView::OnDraw(CDC* pDC)
{
CMonitorDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
pDoc->m_Viewfinder.Draw(pDC) ;//显示矩形“橡皮筋框架”
}

我添加了对应移动滚动条的OnScroll函数以使得OnDraw函数得以响应,
BOOL CMonitorView::OnScroll(UINT nScrollCode, UINT nPos, BOOL bDoScroll)
{
CRect rectTrue ;
CMonitorDoc* pDoc = GetDocument();
ASSERT(pDoc != NULL) ;
pDoc->m_Viewfinder.GetTrueRect(&rectTrue); //获得“橡皮筋框架”
InvalidateRect(&rcClientTrue); //设置待更新显示矩形区域
}
但是问题依然存在




CRectTracker本来就是直接画到屏幕上的,没有通过正常的WM_PAINT消息处理过程来画。
你应该把画图部分封装出来给拖放过程和重画过程共享。MSDN中的DrawCli示例(MFC)可以作为参考。




使用CHtmlView,希望能在页面下载后,使页面自动滚屏 (VC/MFC HTML/XML )




HRESULT CMyDHTMLDialog::scrollToBottom()
{
HRESULT hr= S_FALSE;
IDispatch* spDoc=NULL;
m_pWebBrowseAPPr->get_Document(&spDoc);
if(pDoc)
{
IHTMLDocument2 *pHTMLDoc = NULL;
theResult = pDoc->queryInterface(IID_IHTMLDocument2, (LPVOID*)&pHTMLDoc);
ASSERT(pHTMLDoc);
IHTMLElement *pBody = NULL;
hr= pHTMLDoc->get_body(&pBody);
ASSERT(pBody);
IHTMLElement2 *pElement = NULL;
hr= pBody->QueryInterface(IID_IHTMLElement2,(LPVOID*)&pElement);
ASSERT(pElement);
pElement->put_scrollTop(1000000); // Scroll to bottom.
hr= pElement->Release();
hr= pBody->Release();
hr= pHTMLDoc->Release();
hr= pDoc->Release();
}
return hr;
}




让IE通过程序控制实现滚动的方法,谢谢(VC/MFC 界面)




我想通过程序控制,使IE(Internet Explorer)浏览器滚动起来,比如在IE中输入www.sina.com.cn,由于新浪的首页很长,因此IE会出现一个垂直滚动条,请问如何通过程序控制使IE的水平和垂直滚动条能够滚动起来?我试过了给指IE窗口发送WM_VSCROLL消息,可是不行。请问哪位知道如何实现??谢谢!

我想实现的东西,简单来说,可以抽象成下面的函数:

void ScrollIE(HWND hWndIE, BOOL bVertical)
{
// 如果bVertical为TRUE, 则使句柄hWndIE对应的IE窗口的
// 垂直滚动条从最顶部逐步滚动到最底部,每次向下滚动1/3屏幕;
// 如果bVertical为FALSE, 则使句柄hWndIE对应的IE窗口的
// 水平滚动条从最左端逐步滚动到最右端,每次向右滚动1/3屏幕;

// IE主窗口的内容也应随着滚动条的滚动而相应滚动
}




#include <Mshtml.h>
#include <atlbase.h>
#include <oleacc.h>
void ScrollIE(HWND hWnd, BOOL bVertical)
{
RECT rc;
::GetClientRect(hWnd, &rc);
IHTMLDocument2* pDoc2 = NULL;
LRESULT lRes;
HINSTANCE hInst = ::LoadLibrary( _T("OLEACC.DLL") );

UINT nMsg = ::RegisterWindowMessage( _T("WM_HTML_GETOBJECT") );
::SendMessageTimeout(hWnd, nMsg, 0L, 0L, SMTO_ABORTIFHUNG, 1000, (DWORD*)&lRes );
LPFNOBJECTFROMLRESULT pfObjectFromLresult = (LPFNOBJECTFROMLRESULT)::GetProcAddress( hInst, _T("ObjectFromLresult") );
if ( pfObjectFromLresult != NULL )
{
HRESULT hr;
IHTMLDocument2* pDoc;
hr = (*pfObjectFromLresult)( lRes, IID_IHTMLDocument, 0, (void**)&pDoc);
if ( SUCCEEDED(hr) )
{
CComPtr<IDispatch> spDisp;
CComQIPtr<IHTMLWindow2> spWin;
pDoc->get_Script( &spDisp );
pDoc->Release();
spWin = spDisp;
if (bVertical)
spWin->scroll(0, (rc.bottom -rc.top)/3);
else
spWin->scroll((rc.right-rc.left)/3, 0);

}
}
}
指定一个很大的滚动距离就可以从最顶部滚动到最底部,访问body的scroll*属性可以知道IE窗口的总象素宽度和总的象素高度(包括不可见部分)。


IHTMLDocument2* pDocument;
spWin->get_document(&pDocument);
IHTMLElement* pElement;
pDocument->get_body(&pElement);
IHTMLElement2* pElement2;
pElement->QueryInterface(IID_IHTMLElement2, (void**)&pElement2);
long iHeight;
pElement2->get_scrollHeight(&iHeight);
long iWidth;
pElement2->get_scrollWidth(&iWidth);




如何得到WebBrowser控件里网页的源代码?? (.NET技术 C# )




document.body.innerHTML得到只是body里的源码,我要得到整个网页的源码




using(FileStream stream = new FileStream(@"c:\mafile.txt", FileMode.Create,
FileAccess.Write, FileShare.None) ) {
ComStream cstream = new ComStream( stream );
IPersistStreamInit persistentStreamInit =
(IPersistStreamInit)axWebBrowser1.Document;
persistentStreamInit.Save( cstream, 0 );
http://www.dotnet247.com/247reference/msgs/8/43441.aspx




如何在VC6下生成缩略图? (VC/MFC 图形处理/算法 )




打开jpg 或 bmp 图片文件,快速生成象Windows资源管理器中的缩略图?要求对批量图片处理,速度要快,不是对每副图片直接进行图形变换。
象Windows资源管理器中快速批量生成缩略图一样。




1 只有在要显示之前才生成缩略图
2 在硬盘上生成缓存的交换文件,缓存过大容易造成内存不足影响性能
3 在内存中缓存最近查看的少量缩略图
4 监视文件夹的文件更改以更新内存和磁盘中的缩略图缓存




MFC 与 .NET (.NET技术 .NET Framework)




请比较一下这两者




哪个更有前途?你要二选一?这两个又不是互斥的,只是两个类库而已。


MFC的很多类和函数依赖于线程和模块的状态(包括CString::LoadString,CWnd::AssertValid等等),这样如果你的线程中用到了这些MFC的类和函数,那么这个线程就需要是MFC创建的。MFC的消息和命令的处理流程也和.Net的有区别,以至于在MFC程序中嵌入.Net代码十分繁琐。

.Net 1.0不支持将.Net控件嵌入MFC控件容器,但是从.Net 1.1开始支持了这个做法。MFC 8.0则增加了一些模板类来简化在MFC程序中嵌入WinForm的工作。


MFC的DLL是非托管的,但是可以和托管代码一起工作。托管代码中当然可以引用程序集


混合了非托管代码的程序很可能较难不加修改的移植到其它平台,尤其是在非托管代码包含对特定操作系统的API调用的情况下




为什么在mainframe里给菜单项加消息处理没问题,在view类里这样做菜单项会变灰(.NET技术 VC.NET )




我的SDI程序用CSplitterWindow分为2个View,我想在右边的view里处理菜单消息,结果加了消息映射后菜单还是无效,如果把消息加到mainframe下就好了,请教原因是什么?我想加到View里应该如何做?




命令消息首先被CWinApp类处理,默认的处理流程是CWinApp类->主框架->MDI子框架->活动视图->文档。如果你要自定义处理流程,可以在处理流程中处理这个命令并/或转发到其他CCmdTarget派生类。只有一个视图的时候,视图总是框架的活动视图。用户可以通过界面操作来设置活动视图。如果要用程序设置,调用CSplitterWnd::SetActivePane

参考
http://www.codeproject.com/docview/splitcmdroute.asp




如何保存打印设置(VC/MFC 基础类)




对CPrintDialog
多个打印机,我想选定一个,之后每次打印的时候不需要再选择了。
需要把选定的打印机保存到磁盘中
 




http://support.microsoft.com/kb/q166129/




怎样实现视图的比例缩放(VC/MFC 基础类)




我想在controlBar上放一个Combo Box控件,然后象word那样可以选定缩放比例进行视图缩放?还有,如何controlBar如何停靠在工具栏的右边?




http://www.codeproject.com/docview/McCZoomView.asp
http://msdn.microsoft.com/library/en-us/vcsample/html/_sample_mfc_CTRLBARS.asp
http://search.csdn.net/Expert/topic/714/714468.xml




VB.net使用脚本,如何让脚本访问主程序的过程或函数(.NET技术 VB.NET )




读了《VB-Helper:坚守脚本》
(见http://www.microsoft.com/china/msdn/library/langtool/vbnet/VSFreakOut.mspx)
有很多疑问。
我下载了示例,由两个工程构成,一个主程序,一个DLL
脚本可以访问DLL中的过程和函数,但我不知道DLL中的过程如何去调用主程序的过程(我不知道用没有这个可能性)
我想知道如何才能实现通过脚本去访问主程序中的过程、函数。
例如主程序中有一个模块,其中有一个全局子程序AAA,如何才能使得脚本中可以使用AAA子程序?
顶着有分。恳请大家指教。




.Net可以使用反射,但是你或许会被反射搞昏头。

一个常见的解决方案是声明一些全局对象,类似于IE的脚本引擎中的window对象或者Office自动化中的_Application对象。脚本引擎需要做一些工作来在用户访问之前初始化这些全局对象。全局或者内建函数也是可以考虑的做法。




关于ActiveX使用默认参数的问题(VC/MFC ATL/ActiveX/COM )




我使用ActiveX控件包装了自己的一个类, 但是如何把类方法中缺省默认参数引出去?
也就是说如何在ActiveX中使用缺省的默认参数?




I dont know of any way you can use Class Wizard to add methods that have
optional parameters. The way that I created the methods was to add the
optional parameter in the .odl. The optional parameter needs to be of type
VARIANT. When VB (or anyone else) calls the function without the optional
parameter the VARIANT will contain VARIANT.vt = VT_ERROR VARIANT.scode =
DISP_E_PARAMNOTFOUND.

.idl (may be slightly different syntax in .odl)

[id(1030), helpstring("method Close")] HRESULT Close([in, optional] VARIANT
bSaveChanges, [in, optional] VARIANT strFileName);

.h

STDMETHOD(Close)(THIS_ /*[in, optional]*/ VARIANT varSaveChanges, /*[in,
optional]*/ VARIANT varFileName);

.cpp

STDMETHODIMP CDoc::XDoc::Close
(
VARIANT varSaveChanges
,VARIANT varFileName
)
{
....
}

Check out KB articles
Q154039 How To Pass Optional Arguments to MFC ActiveX Controls
Q158451 How To Call Automation Methods with Variable Argument Lists




如何实现COM中类的嵌套(VC/MFC ATL/ActiveX/COM )




比如:Product类
-Part类
-ADD方法

我调用的时候,可以实现如下:product.part.add




这是通过IDispatch类型的属性来实现的。参加http://msdn.microsoft.com/library/en-us/vcmfc98/html/_mfcnotes_tn065.asp




请问在ActiveX控件里面怎么做出CScrollView那种可以滚动的效果 (VC/MFC ATL/ActiveX/COM )




直接对滚动条进行设置的话就得处理好多消息,还得在画的时候算坐标




在控件里创建一个SCrollView


Designing ActiveX Components with the MFC Document/View Model
By exploiting MFC's poorly understood document/view model, you can give your ActiveX component many great features with relatively little effort

http://www.microsoft.com/mind/0497/mfc.asp




为什么在windows服务程序中WinInet API访问不了外网(VC/MFC 网络编程 )




HttpSendRequest失败, 错误是连接失败。同样的程序在非服务状态下是可以访问外网的。在服务状态下可以访问内网的web服务器,却访问不了外网。难道是服务安全配置的问题?请教




INFO: WinInet Not Supported for Use in Services
http://support.microsoft.com/kb/q238425/




AcitveX控件使用了GDI+后,编译的时候为什么会死机?(VC/MFC ATL/ActiveX/COM )




就在这一步:
Registering ActiveX Control...

我是在App类的InitInstance中初始化的Gdi+,把初始化语句去掉以后就好了,但GDI+的类也不能用了

BOOL CLAvxApp::InitInstance()
{
BOOL bInit = COleControlModule::InitInstance();

if (bInit)
{
if(GdiplusStartup(&m_gdiplusToken, &m_gdiplusStartupInput, NULL)!=Ok){
return FALSE;
}
}

return bInit;
}




不能这样做。CLAvxApp::InitInstance实际上是封装了DLLMain,而GdiplusStartup本质上是加载GDI+的DLL,这会间接调用CLAvxApp::InitInstance封装的DLLMain,造成死锁。你可以在ActiveX的构造函数中初始化GDI+。




如何修改WMV文件的版权信息(VB 多媒体 )




如何修改WMV文件的版权信息!
就是我自己编写的程序已经压缩成WMV了!
没有版权限制!
这时我需要一个程序可以把我自己的WMV文件的版权标题等信息进行任意修改!




参考MetadataEdit示例(MSDN)
http://msdn.microsoft.com/library/en-us/wmform95/htm/sampleapplications.asp

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wmform95/htm/iwmheaderinfointerface.asp

http://msdn.microsoft.com/library/en-us/wmform95/htm/workingwithmetadata.asp




WebBrowse中,如何将页面滚动到指定位置(VC/MFC ATL/ActiveX/COM )




例如模仿查找功能,查找一段链接或者一段文字,找到后自动调到该位置。
已经可以拿到页面的各个元素了,但是无法定位它们在页面中的位置。




scrollIntoView


You can also determine the location, width, and height of an object by using a combination of the IHTMLElement::offsetLeft, IHTMLElement::offsetTop, IHTMLElement::offsetHeight, and IHTMLElement::offsetWidth properties. These numeric properties specify the physical coordinates and dimensions of the object relative to the object's offset parent.

For more information about how to access the dimension and location of objects on the page through the Dynamic HTML (DHTML) Document Object Model (DOM), see Measuring Element Dimension and Location.

http://msdn.microsoft.com/workshop/author/om/measuring.asp




如何在MFC程序中不使用Unicode编译而创建支持Unicode的窗口? (VC/MFC 进程/线程/DLL )




现在我需要让程序窗口(使用了MFC)支持Unicode文字的显示,如果能进行Unicode版的编译就很好了,
可是由于程序原来的设计就没有考虑到Unicode版编译的问题,移植的工作量非常大,
我在网上看到有人介绍了一种方法:在非Unicode版的程序上,通过调用RegisterClassExW来注册窗口类,调用CreateWindowExW来创建窗口,使得窗口成为支持Unicode的窗口.
我在一个没使用MFC的程序中用此法成功了,可是在用了MFC的程序中却无法成功,程序没有报错,但创建的窗口却不是Unicode的(IsWindowUnicode()返回false)
请问这是为什么?有办法解决吗?




Create your window in a seperate module. Write a COM object such as ActiveX, for example.

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/windowing/windows/windowreference/windowfunctions/iswindowunicode.asp

The character set of a window is determined by the use of the RegisterClass function. If the window class was registered with the ANSI version of RegisterClass (RegisterClassA), the character set of the window is ANSI. If the window class was registered with the Unicode version of RegisterClass (RegisterClassW), the character set of the window is Unicode.




通过IHTMLElement的put_innerText方法更改对象的内容为什么会自动转换为HTML代码呢? (VC/MFC ATL/ActiveX/COM )




代码如下:

IHTMLDocument3 *doc;
IHTMLElement *ele;
CppWebBrowser1->Document->QueryInterface(IID_IHTMLDocument3,(void**)&doc);
HRESULT ret = doc->getElementById(L"insScript", &ele);
if(ret == S_OK)
{
ele->put_innerText(L"<script language=javascript>\r\n</script>");
}

这样插入的脚本并不会执行, 而且断行地方,会自动加上<br/>,这可不是我想要的啊?




void CCEditView::OnInsertScript()
{
CInsertScriptDlg* pDlg = new CInsertScriptDlg();
CString strPos = "BeforeEnd";
pDlg->m_strScript = "Insert your script here:";

if ( pDlg->DoModal() == IDOK )
{
IHTMLElement *pElement= NULL;
if (SUCCEEDED(HrGetElementFromSelection(&pElement)))
{
CString strScript = (!pDlg->m_bVB) ?
("&nbsp<script Language=JScript>\n<!-- \n" + pDlg->m_strScript + "\n// -->\n</script>")
: ("&nbsp<script Language=VBScript>\n<!-- \n" + pDlg->m_strScript + "\n' -->\n</script>");
BSTR bstrPos = strPos.AllocSysString();
BSTR bstrContent = strScript.AllocSysString();
pElement->insertAdjacentHTML( bstrPos, bstrContent );
::SysFreeString(bstrPos);
::SysFreeString(bstrContent);
pElement->Release();
}
}
delete pDlg;
}

No comments: