VC++.NET 2005 几个比较难缠的问题及其解决方法

       问题一:HWND和System::Inptr32的转换
如果你用惯了VB.NET,你一定会认为窗体的Handle属性就等同于API里面要的那个HWND——的确,MSDN里面就是这么说的,而且,在VB.NET里你可以这样写ShowWindow(Me.Handle,SW_SHOW),这一切看上去没有错误,而且字面意思上是如此理所当然。但是,进入了CLR C++的环境,ShowWindow(this->Handle,SW_SHOW)的直接结果就是编译器扔给你一句编译错误:类型不匹配,无法将System::Inptr32转换为HWND。
 
事实很明显,Handle并不如MSDN里面说的那样就是HWND,VB.NET在把Handle传进API的时候进行了类型转换,如果你有把VB.NET程序移植到CLR C++或者在CLR C++里面使用用VB.NET的程序集的经验,就会对这些深有体会。CLR C++最大的问题在于,它对绝大部分的.NET数据类型都要求用户显式地转换,而着对于.NET Framework来说没有类型自动转换显然是非常痛苦的。
我们再说回这个Handle,可能有人会这样说,我这样写可不可以呢?
ShowWindow(HWND(this->Handle),SW_SHOW);
于是编译器再次给了你脸色看,还是那个错误。
 
接着就有人发现,Handle还有一个方法 ToPointer,这次看上去问题肯定能解决了,不是么?Pointer就是指针,HWND不也是一个指针吗?于是,又有人提议:
ShowWindow(this->Handl.ToPointer(),SW_SHOW);
意思上是完美了,但是,非常遗憾,编译器说:我只认类型,不看意思,于是又报了一个错误出来。
 
做到这里,看上去已经是山穷水尽了。其实失败和成功只有一步之遥:HWND和void*是可以互相转换的!我们只要再继续多写一步:
ShowWindow(HWND(this->Handle.ToPointer()),SW_SHOW);
问题就可以解决。
接下来是第二个问题,还是这个ShowWindow。并不是所有场合我们都喜欢使用这样的语句:
This->Show();
有时候,我们得使用ShowWindow来达到某些显示的效果。当我们兴高采烈地庆祝我们解决了Handle的转换时,我们会惊讶地发现,ShowWindow显示出来的窗口什么也没有!上面的控件都不见了!
当我看到这个现象的时候,我脑袋里立刻想起一个东西:Borland C++ Builder。
是的,这个现象与Borland C++ Builder里的窗口显示特性简直一模一样!据说.NET Framework总的设计师就是那个大名鼎鼎的从Borland跑到Microsoft的安德森,果然有风格(可惜的就是MFC却没学到VCL的方便,倒是.NET学了这个见鬼的特性)。怎么办呢?细心的人会发现,当我们对窗口执行 this->Show();的时候,显示出来的窗口是无焦点的,也就是说,我们不再需要ShowWindow这个API了(因为这个API一般都是用来显示无焦点的窗体)。我们只要在Show()执行之后设置窗口的WindowState,例如:
Msgform->WindowState =System::Windows::Forms::FormWindowState::Normal ;
 
问题三:打包安装。
程序写完了,以为终于可以松口气了。把程序和.NET Framework安装包拿到别人那里一安装,居然发觉弹出个错误对话框:程序配置不正确。
这是典型的缺少运行时错误。于是就奇怪,MSDN不是说.NET程序可以XCopy部署的么?只要有.NET Framework ,就只要拷贝程序到目标机器上面就可以运行的啊??!!
的确,对于vb和C#的程序,xcopy部署不会存在任何问题,因为这两门语言都是给.NET量身订做的。但是C++不是。结果回去查看了vb.net程序和clr c++程序引用的dll,发现托管的C++程序比vb.net程序多引用两个dll:
                 MSVCR80D.dll
                 MSVCM80D.dll
然后我用reflector反编译我的程序,发现程序配置头xml文件里面有如下内容:
 
 
 
<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
 <dependency>
    <dependentAssembly>
      <assemblyIdentity type='win32' name='Microsoft.VC80.DebugCRT' version='8.0.50608.0' processorArchitecture='x86' publicKeyToken='1fc8b3b9a1e18e3b' />
    </dependentAssembly>
 </dependency>
</assembly>
 
注意Microsoft.VC80.DebugCRT(当你编译程序使用Debug模式就会产生)!
刚刚说的那两个dll就是Microsoft.VC80.DebugCRT的部件,现在你知道少了什么了吧?
于是我们必须把Microsoft.VC80.DebugCRT组件一起安装到目标机器上面。但是Microsoft.VC80.DebugCRT上哪找呢?
我们新建一个安装部署项目,然后添加合并模块,你会看到打开的默认文件夹里面有这个文件:
 
 
           policy_8_0_microsoft_vc80_debugcrt_x86.msm
 
猜都猜到这是什么了吧?添加进去!
当然,如果你编译使用的是Release模式,你可能依然需要安装VC++.NET 的一个可再发行包组件。
posted @ 2006-09-08 15:53  huxi  阅读(211)  评论(0编辑  收藏  举报