2009年1月4日

   C++ Templates读书笔记< 三 > 类模板,非类型模板

类模板:

* 如果类模板中含有静态成员,那么用来实例化的每种类型,都会实例化这些静态成员。

* 两个靠在一起的模板尖括号( > ) 之间需要留个空格,否则,编译器将会认为是在使用operator>>,导致语法错误。

* 特化的实现可以和基本类模板的实现完全不同。

* 类模板可以为模板参数定义缺省值,称为缺省模板实参,并且他们还可以引用之前的模板参数。

* 成员函数模版不能被声明为虚函数。

* 类模板不能和另外一个实体共享一个名称。

eg:

1         int C;
2 
3         class C;    // ok,    
4 
5         int X;
6 
7         template < typename T >
8 
9         class X;    // error. 和变量X冲突

非类型模板参数:

在编译期或链接期可以确定的常值。这种参数的类型必须是下面的一种:

a> 整型或枚举

b> 指针类型( 普通对象的指针,函数指针,成员指针 )

c> 引用类型( 指向对象或者指向函数的引用 )

其他的类型目前都不允许作为非类型模板参数使用

eg:内部链接对象不允许作为非类型模板参数

 1             template < char const* name >
 2 
 3             class MyClass
 4 
 5             {
 6 
 7             };            
 8 
 9             char const* s = "hello";
10 
11             MyClass<s> x;    // error; s是一个指向内部链接对象的指针            
12 
13             extern char const s[] = "hello";
14 
15             MyClass<s> x;    // ok; s是一个外部链接对象


 版权声明:本篇为原创文章,允许转载,但转载时请务必以超链接形式标明文章的原始出处和作者信息。请尊重本人的劳动成果,谢谢!

posted @ 2009-01-04 21:28 小祥 阅读(321) | 评论 (0)编辑
 
   Scaleform实现图文混排 Using embedded images in TextField

据Scaleform官方讲,GFx2.0 alpha5版本已经支持了用图片替换字符串的功能, 并且在alpha6版本中加入了对HTML < IMG > 标签的支持。所以实现图文混排,目前有2种方法:
1。Substitution of character strings with images  图片替换字符串
要替换的图片需要一个导出名。具体步骤如下:
a> 导入一个bitmap到库。 ( 文件 --> 导入 --> 导入到库 ) 
b> 在库面板图片名称上点右键,然后在弹出菜单上选择“链接”。
c> 选择“Export for ActionScript(为ActionScript导出)”和“Export in first Frame(在第一帧导出)”,然后在标识符里写入导出名(例如myImage)。
d> 填好名字后点“确定”...
到这里,图片的导出名就已经定义好了。导出名将会在创建BitmapData时用到。例如:
        import flash.display.BitmapData; 
        var imageBmp:BitmapData 
= BitmapData.loadBitmap("myImage"); 
注意:“import flash.display.BitmapData”不能省略,不然结果将会是"undefined"!
GFx 2.0为Flash的TextField扩展了两个函数: "setImageSubstitutions" 和 "updateImageSubstitution"。这里只用setImageSubstitutions这个函数。
    public setImageSubstitutions(substInfoArr:Array); 
    
public setImageSubstitutions(substInfo:Object);
"substInfoArr"是以个数组,里面的每个Object都应该包含下列属性:
subString:String - 制定将要被替换的字符串,该参数不能省
image : BitmapData - 用来替换上面制定的字符串的图片名称(前面定义好的导出名),该参数不能省
width : Number - 图片宽, 可选参数
height : Number - 图片高, 可选参数
baseLineY : Number - Y偏移,默认=图片高, 可选参数
id : String - 制定一个id供"updateImageSubstitution"函数来调用, 可选参数
注意:"setImageSubstitutions" 会加入到一个内部的列表。若想取消上述设置的话只需要调用"setImageSubstitutions",参数为"null"。
 
下面是我的例子:
        _global.gfxExtensions = true;
        import flash.display.BitmapData;

        var b1:BitmapData 
= BitmapData.loadBitmap( "bitmap1" );
        var b2:BitmapData 
= BitmapData.loadBitmap( "bitmap2" );
        var b3:BitmapData 
= BitmapData.loadBitmap( "bitmap3" );
        var b4:BitmapData 
= BitmapData.loadBitmap( "bitmap4" );
        var b5:BitmapData 
= BitmapData.loadBitmap( "bitmap5" );
        var b6:BitmapData 
= BitmapData.loadBitmap( "bitmap6" );
        var b7:BitmapData 
= BitmapData.loadBitmap( "bitmap7" );
        var b8:BitmapData 
= BitmapData.loadBitmap( "bitmap8" );
        var b9:BitmapData 
= BitmapData.loadBitmap( "bitmap9" );
        var b10:BitmapData 
= BitmapData.loadBitmap( "bitmap10" );

        var a 
= new Array;
        a[
1= { subString:"xiao1", image:b1 };
        a[
2= { subString:"xiao2", image:b2 };
        a[
3= { subString:"xiao3", image:b3 };
        a[
4= { subString:"xiao4", image:b4 };
        a[
5= { subString:"xiao5", image:b5 };
        a[
6= { subString:"da1", image:b6 , baseLine:20, width: 64, height:64};
        a[
7= { subString:"da2", image:b7 , baseLine:20, width: 64, height:64};
        a[
8= { subString:"da3", image:b8 , baseLine:20, width: 64, height:64};
        a[
9= { subString:"da4", image:b9 , baseLine:20, width: 64, height:64};
        a[
10= { subString:"da5", image:b10 , baseLine:20, width: 64, height:64};
        m_mcText.setImageSubstitutions( a );

        m_mcText.autoSize 
= true;
        m_mcText.html 
= true;
        m_mcText.htmlText 
= "<font size='24' color='#0000FF'>This is blue</font>, xiao1, da1 24-point text";

   效果图:

     

2. Using <IMG> tag in HTML ,通过HTML < IMG >标签
先看一个例子:
t.htmlText = "<p align='right'>abra<img src='myImage' width='20' height='30' align='baseline' vspace='-10'>bed232</p>"; 
"myImage"是导出名,具体步骤看上面
当前< IMG >标签标签支持的属性如下:
src - 链接名,不能省略

width - 图片宽

height - 图片高

align - 目前只支持"baseline". 

vspace - 

不支持的属性:

id - Specifies the name for the movie clip instance (created by Flash Player) that contains the embedded image file, SWF file, or movie clip. 

align - "left" and "right". Specifies the horizontal alignment of the embedded image within the text field. 

hspace - For "left" and "right" it specifies the amount of horizontal space that surrounds the image where no text appears. 
以上两种方法,我只试验成功了方法1,方法2暂没成功,有成功的不妨告诉下。
另外这种方法实现的图文混排,只支持静态bitmap,想做成动态表情那样的话就需要用到updateImageSubstitution函数了,原理也简单,就是序列帧动画。

最后,再说明一下,_global.gfxExtensions = true 是必须的


版权声明:本篇为原创文章,允许转载,但转载时请务必以超链接形式标明文章的原始出处和作者信息。请尊重本人的劳动成果,谢谢!
小祥的BLOG http://xfxsworld.cnblogs.com

 

 

 

posted @ 2009-01-04 13:12 小祥 阅读(274) | 评论 (3)编辑

2009年1月2日

   C++ Templates读书笔记< 二 > Tricky Basics

* 关键字typename,用来说明某个标志符是个型别.

eg: 
1         template < typename T >
2         class MyClass
3         {
4             typename T::SubType* ptr;
5             
6         };
* assignment运算的template版本并不会取代default assignment运算

* 双重模板参数: Template Template Parameters
eg:
 1         template < typename T, 
 2                 template < typename ELEM
 3                            typename ALLOC = std::alloctator<ELEM> > 
 4                 class CONT = std::deque
 5                 >
 6         class Stack
 7         {
 8             COUT<T> elems;        // 以第一个参数的型别完成了实例化, 也可以利用class template内的任何型别 来实例化
10         };
11     // 注:template template arguments必须完全匹配对应的参数。预设的template arguments会被编译器忽略。
12     // 所以,如果上面没有写 typename ALLOC = std::alloctator<ELEM> 就会报错
function templates 不允许拥有template template parameters
* 初始化
eg:
 1         template < typename T >
 2         class MyClass
 3         {
 4         private:
 5             T x;
 6         public:
 7             MyClass()
 8                 : x()    // 即使T为build-in type,x也可以被初始化
 9             {
10             }
11         };

* 只有by value传参时,才会发生 array to pointer 的转换

eg:

 1 template < typename T >
 2         inline T const& max( T const& a, T const& b )
 3         {
 4             return a < b ? b : a;
 5         }
 6         
 7         max( "apple""peach" );    // ok
 8         max( "apple""tomato" );    // error, 型别不同,一个是char const[6],一个是char const[7]
 9         
10         template < typename T >
11         inline T max( T a, T b )
12         {
13             return a < b ? b : a;
14         }
15         
16         max( "apple""peach" );    // ok
17         max( "apple""tomato" );    // ok, 发生了array to pointer的转换, 但比较结果是错的,因为实际上比较的是指针地址


版权声明
:本篇为原创文章,允许转载,但转载时请务必以超链接形式标明文章的原始出处和作者信息。请尊重本人的劳动成果,谢谢!

小祥的BLOG http://xfxsworld.cnblogs.com 

 

posted @ 2009-01-02 16:06 小祥 阅读(74) | 评论 (0)编辑

2009年1月1日

  C++ Templates读书笔记< 一 > 函数模版

* 并不是把模板编译成一个可以处理任何类型的单一实体,而是对于实例化模板参数的没种类型,都从模板产生出一个不同的实体。
* 具体类型代替模板参数的过程,叫做“实例化”
* 模板被编译了两次:
1。 实例化之前,检查模板本身的语法
2。 实例化期间,察看是否所有的调用都有效
* 函数模板内部,不能制定缺省的模板实参(类模板可以)。
* 函数模板的实参演绎:调用参数的类型构造自模板参数,所以模板参数和调用参数通常是相关的。
 模板实参演绎并不适合返回类型。
* eg:
            1 template< typename T1, typename T2 >
                 2 inline T1 max( T1 const& a, T2 const& b )
                 3 {
                 4      return a < b ? b : a;
                 5 }
注:返回类型不能是引用。因为若返回T2类型实参,则T2需要转为T1,这个过程将会创建一个新的局部临时变量。
* 重载函数模版:
a> 一个非模板函数可以和一个同名的模版函数同时存在,并且该模板函数还可以被实例化为这个非模板函数。
b> 模板不允许自动类型转换,但普通非模板函数可以。
eg:
 1         inline int const& max( int const& a, int const& b )
 2         {
 3             return a < b ? b : a;
 4         }
 5         
 6         template< typename T >
 7         inline T const& max( T const& a, T const& b )
 8         {
 9             return a < b ? b : a;
10         }
11         
12         max( 7.042.0 );       // 调用max<double>
13         max( 'a''b' );         // 调用max<char>
14         max( 742 );            // 调用int重载的非函数模板
15         max<>742 );        // 调用max<int>            上述 a>
16         max<double>742 ); // 调用max<double>    没有实参演绎
17         max< 'a'42.7 >;      // 调用int重载的非函数模板    上述 b>
c> 函数的所有重载版本的声明都应该位于函数被调用的位置之前

版权声明:本篇为原创文章,允许转载,但转载时请务必以超链接形式标明文章的原始出处和作者信息。请尊重本人的劳动成果,谢谢!
小祥的BLOG http://xfxsworld.cnblogs.com
posted @ 2009-01-01 17:43 小祥 阅读(108) | 评论 (0)编辑

2008年3月22日

                                                               译:理解 Win32 "OutputDebugString"

坚定的 Win32 开发人员可能对 OutputDebugString() API 函数比较熟悉,它可以使你的程序和调试器进行交谈。它要比创建日志文件容易,而且所有“真正的”调试器都能使用它。应用程序和调试器交谈的机制相当简单,而本文将揭示整件事情是如何工作的。

本文首先是由以下事件促使的,我们观察到 OutputDebugString() 在管理员和非管理员用户试图一起工作或游戏时并不总是能可靠地工作(至少在 Win2000 上)。我们怀疑是一些相关的内核对象的权限问题,此间涉略了相当多不得不写下来的信息。

请注意,尽管我们使用了“调试器”这一术语,但不是从调试 API 的意义上来使用的:并没有“单步执行”、“断点”或者“附着到进程”等可以在 MS Visual C 或者一些真正的交互开发环境中找到的东西。从某种意义上来说,任何实现了协议的程序都是“调试器”。可能是一个非常小的命令行工具,或者像来自于 SysInternals 那帮聪明的家伙们的 DebugView 那样的高级货。

内容目录

应用程序用法

<windows.h> 文件声明了 OutputDebugString() 函数的两个版本 - 一个用于 ASCII,一个用于 Unicode - 不像绝大多数 Win32 API 一样,原始版本是 ASCII。而大多数的 Win32 API 的原始版本是 Unicode。

使用一个 NULL 结尾的字符串缓冲区简单调用 OutputDebugString() 将导致信息出现在调试器中,如果有调试器的话。构建一条信息并发送之的通常用法是:


sprintf(msgbuf, "Cannot open file %s [err=%ld]\n", fname, GetLastError());
OutputDebugString(msgbuf);

不过在实际环境中我们中的不少人会创建一个前端函数,以允许我们使用 printf 风格的格式化。下面的 odprintf() 函数格式化字符串,确保结尾有一个合适的回车换行(删除原来的行结尾),并且发送信息到调试器。


#include <stdio.h>
#include <stdarg.h>
#include <ctype.h>
void __cdecl odprintf(const char *format, ...)
{
char buf[4096], *p = buf;
va_list args;
va_start(args, format);
p += _vsnprintf(p, sizeof buf - 1, format, args);
va_end(args);
while ( p > buf  &&  isspace(p[-1]) )
*--p = '\0';
*p++ = '\r';
*p++ = '\n';
*p   = '\0';
OutputDebugString(buf);
}

于是在代码中使用它就很简单:


        ...
odprintf("Cannot open file %s [err=%ld]", fname, GetLastError());
...

我们已经这样使用多年了。

协议

在应用程序和调试器之间传递数据是通过一个 4KB 大小的共享内存块完成的,并有一个互斥量和两个事件对象用来保护对他的访问。下面就是相关的四个内核对象:

对象名称 对象类型
DBWinMutex Mutex
DBWIN_BUFFER Section (共享内存)
DBWIN_BUFFER_READY Event
DBWIN_DATA_READY Event

互斥量通常一直保留在系统中,其他三个对象仅当调试器要接收信息才出现。事实上 - 如果一个调试器发现后三个对象已经存在,它会拒绝运行。

当 DBWIN_BUFFER 出现时,会被组织成以下结构。进程 ID 显示信息的来源,字符串数据填充这 4K 的剩余部分。按照约定,信息的末尾总是包括一个 NULL 字节。


struct dbwin_buffer {
                DWORD   dwProcessId;
                char    data[4096-sizeof(DWORD)];
                };
                

OutputDebugString() 被应用调用时,它执行以下步骤。注意在任意位置的错误都将放弃整个事情,调试请求被认为是什么也不做(不会发送字符串)。

  1. 打开 DBWinMutex 并且等待,直到我们取得了独占访问。
  2. 映射 DBWIN_BUFFER 段到内存中:如果没有发现,则没有调试器在运行,将忽略整个请求。
  3. 打开 DBWIN_BUFFER_READYDBWIN_DATA_READY 事件对象。就像共享内存段一样,缺少对象意味着没有可用的调试器。
  4. 等待 DBWIN_BUFFER_READY 事件对象为有信号状态:表示内存缓冲区不再被占用。大部分时候,这一事件对象一被检查就处于有信号状态,但等待缓冲区就绪不会超过 10 秒(超时将放弃请求)。
  5. 复制数据直到内存缓冲区中接近 4KB,再保存当前进程 ID。总是放置一个 NULL 字节到字符串结尾。
  6. 通过设置 DBWIN_DATA_READY 事件对象告诉调试器缓冲区就绪。调试器从那儿取走它。
  7. 释放互斥量。
  8. 关闭事件对象和段对象,但保留互斥量的句柄以备后用。

在调试器端会简单一点。互斥量根本不需要,如果事件对象和/或共享内存对象已经存在,则假定其他调试器已经在运行。系统中任意时刻只能存在一个调试器。

  1. 创建共享内存段以及两个事件对象。如果失败,退出。
  2. 设置 DBWIN_BUFFER_READY 事件对象,由此应用程序得知缓冲区可用。
  3. 等待 DBWIN_DATA_READY 事件对象变为有信号状态。
  4. 从内存缓冲区中提取进程 ID 和 NULL 结尾的字符串。
  5. 转到步骤 2。

这使我们认为这决不是一种低消耗的发送信息的方法,应用程序的运行速度会受到调试器的左右。

权限问题

我们发现 OutputDebugString() 有时不可靠已经好几年了,而且我们十分不解为什么微软这么长时间也没把它搞好。奇怪的是,问题总是围绕着 DBWinMutex 对象出现,这就需要我们察看许可系统以找出为什么会这么麻烦。

互斥量对象会一直存活着直到使用它的最后一个程序关闭其句柄,故而它能在初始创建它的应用程序退出后保留相当长的时间。因为此对象被广泛地共享,所以它必须被赋予明确的许可以允许任何人使用它。事实上,“缺省”许可几乎从不适用,这一问题被计为在 NT 3.51 和 NT 4.0 中我们观察到的第一个问题

当时的修正方法是使用一个广泛开放的 DACL 创建互斥量,以此来允许任何人访问它,但是看样子在 Win2000 里这些许可被加强了。表面上它看起来是正确的,就像我们在下表中看到的:

SYSTEM MUTEX_ALL_ACCESS
Administrators MUTEX_ALL_ACCESS
Everybody SYNCHRONIZE | READ_CONTROL | MUTEX_QUERY_STATE

希望发送调试信息的应用只需要等待和获取该互斥量的能力,也即体现为拥有 SYNCHRONIZE 权限。上列的许可对于所有参与的用户都是完全正确的。

不过如果有人观察 CreateMutex() 在对象已经存在时的行为,就会发现奇怪的事情。在这种情况下,Win32 的表现就好像我们进行了如下调用:

OpenMutex(MUTEX_ALL_ACCESS, FALSE, "DBWinMutex");
                        

尽管我们确实只需要 SYNCHRONIZE 访问,但它还是假定调用者要做任何事情MUTEX_ALL_ACCESS)。因为非管理员没有这些权限 - 仅有上列的少许 - 互斥量不能被打开或者获取,于是 OutputDebugString() 不做任何事情就悄悄地返回了。

甚至将所有的软件开发都以管理员来执行也不是一个完整的修正方法:如果存在其他的用户(例如服务)以非管理员运行而许可配置不正确,它们的调试信息将会丢失。

我们感觉真正的修正需要微软为 CreateMutex() 添加一个参数 - 如果对象已经存在时用于隐含的 OpenMutex() 调用的访问掩码。也许某天我们会看到一个 CreateMutexEx(),但在此期间我们必须采用另外的方法。代之以,当对象已经存活于内存中时我们将硬性改变其上的许可配置。

这需要调用 SetKernelObjectSecurity(),下列程序片断展示一个程序如何才能打开互斥量并安装一个新的 DACL。此 DACL 即使在程序退出后也仍然保持着,只要任一其他程序还维护有它(译者注:应该是指互斥量)的句柄。

...
                        // open the mutex that we're going to adjust
                        HANDLE hMutex = OpenMutex(MUTEX_ALL_ACCESS, FALSE, "DBWinMutex");
                        // create SECURITY_DESCRIPTOR with an explicit, empty DACL
                        // that allows full access to everybody
                        SECURITY_DESCRIPTOR     sd;
                        InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);
                        SetSecurityDescriptorDacl(
                        &sd,            // addr of SD
                        TRUE,           // TRUE=DACL present
                        NULL,           // ... but it's empty (wide open)
                        FALSE);         // DACL explicitly set, not defaulted
                        // plug in the new DACL
                        SetKernelObjectSecurity(hMutex, DACL_SECURITY_INFORMATION, &sd);
                        ...
                        

这一方法明确地走向了正确的道路,但我们还需要找一个地方来放置此逻辑。把它放在一个一经请求即运行的小程序中是可以的,但是看起来它有可能被中断。我们的办法是写一个 Win32 服务来干这件事情。

我们的 dbmutex 工具完成的就是这一工作:它在系统引导时启动,打开或者创建互斥量,然后设置对象的安全性以允许广泛的访问。然后休眠直到系统关闭,在此过程中保持互斥量的打开状态。它不消耗任何 CPU 时间。

实现细节

我们花了很多时间使用 IDA Pro 深入到 Windows 2000 KERNEL32.DLL 的实现中,我们认为,对于它在更精确的基础上到底是如何工作的已经有了良好的掌握。在这儿我们给出 OutputDebugString() 函数的伪代码(我们没有编译过它),以及创建互斥量的函数。

我们故意略去了大多数的错误检查:如果事情变糟了,它将释放所有已分配的资源并退出,就像没有调试器存在一样。目的是展示一般行为而不是对代码的完整的逆向工程。

“setup” 函数 - 名字是我们起的 - 创建互斥量或者在已经存在时打开它。经过一些努力来设置互斥量对象的安全性以使任何人都能用它,尽管我们会看到其实并没有完全正确地得到它。

OutputDebugString.txt

胡思乱想

一些人可能会感到这是一个安全性问题,其实并不是。非管理员用户确实拥有适当使用 OutputDebugString() 的所有权限,不过由于“请求比所需更多权限”这一常见问题,一个合理的请求因形成了错误的形态而被拒绝了。

但并不像大部分的这种问题那样,这并非是有意的。大多数的错误是开发人员显式请求了更多(如“MUTEX_ALL_ACCESS”),而这次的掩码是由 CreateMutex() 的行为隐含的。这使得如果 Win32 API 不做改动的话更加难于避免。

---

当分析 KERNEL32.DLL 中的 OutputDebugStringA() 时,非管理员如何能够有可能去削弱系统变得明显起来。一旦得到互斥量,一个要发送调试信息的应用会等待 DBWIN_BUFFER_READY 事件对象就绪最多十秒钟,如果超时则放弃。这看起来是一个谨慎的防范措施,如果调试系统忙的话,用以避免被饿死。

但在更早的步骤里,等待互斥量,没有这样的超时设定。如果系统中的任何进程 - 包括非特权进程 - 可以以请求 SYNCHRONIZE 权限打开此互斥量,并且不释放它,所有其他试图获取此互斥量的进程将会无限停止完蛋。

我们的研究表明,所有类型的程序都会发送随意的调试信息(例如,MusicMatch Jukebox 就有一个唠唠叨叨的键盘钩子),这些线程通过很少的几行代码就能停止住。没有必要停止整个程序 - 可能还有其他的线程 - 但在实际中,开发人员不计划使用 OutputDebugString() 将会是一条拒绝服务之路(译者注:此句没有完全明白,请参看原文)。

---

最奇怪的是,我们发现 OutputDebugString() 并非一个天然的 Unicode 函数。大多数的 Win32 API 具有“真正的”使用了 Unicode 的函数(“W” 版本),如果调用“A”版本的函数则它们自动从 ASCII 转换到 UNICODE。

但是,因为 OutputDebugString 把在内存缓冲区中的数据最终是作为 ASCII 传递到调试器中的,它们具有相反于常规的 A/W 配对。这就暗示了如果要在 Unicode 程序里发送一个快捷信息到调试器,可以通过直接调用 “A” 版本来实现:

OutputDebugStringA("Got here to place X");
                        

本文转自: http://sluttery.spaces.live.com/default.aspx

版权声明:本篇为转载文章,可随意转载或收藏
小祥的BLOG http://xfxsworld.cnblogs.com
posted @ 2008-03-22 16:55 小祥 阅读(2159) | 评论 (0)编辑
 

 将Debug调试信息输出到控制台或文件

        时常会碰到这种情况,策划们跑过来说程序出错了,然后呱呱啦啦的描述了一大堆也没把问题说清楚。若是能将程序的运行信息自动的记录起来,找bug就方便多了,也就是log功能。

        另外为调试程序,时常需要在程序里打入一些调试信息,这样可以更方便的发现BUG。这些调试信息只能在编辑器的调试模式下才能看到,或者借助第三方软件比如debugview等,但是会受到编译环境的限制,又不可能每次都带着debugview运行程序。。。若能将调试信息自动记录到log文件就方便多了。

        在调试模式下,调试器之所以能够得到信息,是因为捕捉了程序中的 OutputDebugString() 输出的信息。所以如果我们能够自己写程序捕捉OutputDebugString()函数输出的信息,就能解决上述的需求了。有关OutputDebugString()函数的原理请看这里:http://www.unixwiz.net/techtips/outputdebugstring.html,也可在本blog查看翻译版本。

        原理看明白后,实现起来就很容易了。下面给出具体代码:

 1const MAX_DebugBuffer = 4096;    // 应用程序和调试器之间传递数据是通过一个 4KB 大小的共享内存块完成的
 2
 3typedef struct dbwin_buffer {
 4    DWORD   dwProcessId;
 5    char    data[4096-sizeof(DWORD)];
 6}
DEBUGBUFFER,*PDEBUGBUFFER;
 7
 8// 线程函数
 9void WINAPI DebugTrackProc(PVOID pvParam)
10{   
11    HANDLE hMapping = NULL;  
12    HANDLE hAckEvent = NULL;
13    HANDLE hReadyEvent = NULL;
14    PDEBUGBUFFER pdbBuffer = NULL;  
15    TCHAR tzBuffer[MAX_DebugBuffer];  
16        
17    // 打开事件句柄    
18    hAckEvent = CreateEvent(NULL, FALSE, FALSE, TEXT("DBWIN_BUFFER_READY"));    
19    if(hAckEvent == NULL)
20    {
21        CloseHandle(hAckEvent); 
22        return;
23    }

24
25    hReadyEvent = CreateEvent(NULL, FALSE, FALSE, TEXT("DBWIN_DATA_READY"));  
26    if(hReadyEvent == NULL)
27    {
28        CloseHandle(hReadyEvent); 
29        return;
30    }
 
31
32    // 创建文件映射  
33    hMapping = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, MAX_DebugBuffer, TEXT("DBWIN_BUFFER"));   
34    if(hMapping == NULL)
35    {
36        CloseHandle(hMapping); 
37        return;
38    }
 
39
40    // 映射调试缓冲区  
41    pdbBuffer = (PDEBUGBUFFER) MapViewOfFile(hMapping, FILE_MAP_READ, 000);  
42  
43    // 循环  
44    whiletrue )
45    {             
46        // 激活事件
47        SetEvent(hAckEvent);  
48        // 等待缓冲区数据
49        if ( WaitForSingleObject(m_hReadyEvent, INFINITE) == WAIT_OBJECT_0 )   
50        {              
51            // 保存信息,这就是我们想要的,有了这个信息,想打log或是输出到控制台就都可以啦      
52            tzBuffer = pdbBuffer->szString;              
53        }
   
54    }
 
55
56    // 释放   
57    if (pdbBuffer) 
58    {      
59        UnmapViewOfFile(pdbBuffer);   
60    }
   
61    CloseHandle(hMapping);   
62    CloseHandle(hReadyEvent);  
63    CloseHandle(hAckEvent);
64}


版权声明:本篇为原创文章,允许转载,但转载时请务必以超链接形式标明文章的原始出处和作者信息。请尊重本人的劳动成果,谢谢!
小祥的BLOG http://xfxsworld.cnblogs.com

posted @ 2008-03-22 16:49 小祥 阅读(643) | 评论 (0)编辑

2008年1月30日

 常量指针与指针常量

常量指针,就是指向常量的指针,关键字 const 出现在 * 左边,表示指针所指向的地址的内容是不可修改的,但指针自身可变。
指针常量,指针自身是一个常量,关键字 const 出现在 * 右边,表示指针自身不可变,但其指向的地址的内容是可以被修改的。

例:
        常量指针: const char* ptr = “hello”
        指针常量: char* const ptr = “hello”

另外常量指针有两种写法:const既可写在类型前,又可写在类型后。如上面的例子,常量指针:char const * ptr = “hello” 也是正确的。

最后再举个例子,与迭代器经常在一起用。
若希望迭代器所指向的东西不可变,则需要的是 const_iterator。例:

std::vector<int>::const_iterator Iter = vec.begin();
*Iter = 10;//错误,Iter是常量指针
Iter++;//正确,Iter本身可变

若希望迭代器本身不可变,指向的内容可变,则可以这样写:
const std::vector<int>::iterator Iter = vec.begin();
*Iter = 10//正确,指针常量
Iter++;     //错误,指针本身不可变

版权声明:本篇为原创文章,允许转载,但转载时请务必以超链接形式标明文章的原始出处和作者信息。请尊重本人的劳动成果,谢谢!
小祥的BLOG http://xfxsworld.cnblogs.com
posted @ 2008-01-30 23:33 小祥 阅读(526) | 评论 (0)编辑

2008年1月29日

     摘要: wxWidgets helper classeswxWidgets库可以创建控制台( console )和界面( gui )程序,下面将在控制台模式下介绍一些helper class。Console这是一个简单得控制台程序,在控制台窗口里输出一些信息。#include<wx/string.h>intmain(intargc,char**argv){wxPuts(wxT("AwxWidg... 阅读全文
posted @ 2008-01-29 21:52 小祥 阅读(565) | 评论 (0)编辑

2008年1月26日

 SplashScreen

     开始学习wxWidgets。准备把学到的都记下来,算是自己的学习笔记。
     今天写了一个SplashScreen的小例子。SplashScreen的意思通俗点来说就是在程序运行前先蹦出来的东东。举个例子,比如游侠网下载的游戏,每次运行前都会蹦出来一个小图片,停留几秒后,等它消失了才会进入游戏。
     大致流程是:1. 加载需要的image handler,下表列出的是wx可用的image handler(可以看出目前只有PNG格式支持alpha通道)
                          
wxBMPHandler For loading and saving, always installed.
wxPNGHandler For loading (including alpha support) and saving.
wxJPEGHandler For loading and saving.
wxGIFHandler Only for loading, due to legal issues.
wxPCXHandler For loading and saving (see below).
wxPNMHandler For loading and saving (see below).
wxTIFFHandler For loading and saving.
wxTGAHandler For loading only.
wxIFFHandler For loading only.
wxXPMHandler For loading and saving.
wxICOHandler For loading and saving.
wxCURHandler For loading and saving.
wxANIHandler For loading only.
    wx默认加载wxBMPHandler,如果要用其他格式,则可以通过调用wxImage::AddHandler()函数进行加载。也可以调用wxImage::wxInitAllImageHandlers()加载所有的,但通常没有这个必要。
                    2. Load图片。
                        通过wxBitmap::LoadFile( const wxString& name, wxBitmapType type )函数。
                        name是将要load进来得图片的名字,type是图片格式的类型,比如bmp格式的图片就是wxBITMAP_TYPE_BMP ,PNG格式的就是wxBITMAP_TYPE_PNG。。。
                    3. 可以创建SplashScreen了。
                        wxSplashScreen(const wxBitmap& bitmap, long splashStyle, int milliseconds, wxWindow* parent, wxWindowID id, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxSIMPLE_BORDER|wxFRAME_NO_TASKBAR|wxSTAY_ON_TOP)
                        具体参数一看就明白意思了。bitmap就是上面第2步创建的,splashStyle是风格,例:wxSPLASH_CENTRE_ON_SCREEN。后面几个参数分别是 持续时间,父窗口指针, id号, 位置, 大小,样式。。

 1wxImage::AddHandler(new wxPNGHandler);
 2
 3    wxBitmap bitmap;
 4
 5    bitmap.LoadFile(_T("splash.png"), wxBITMAP_TYPE_PNG);
 6
 7    wxSplashScreen* const splashScreen = new wxSplashScreen(bitmap,
 8            wxSPLASH_CENTRE_ON_SCREEN|wxSPLASH_TIMEOUT,
 9            -1, NULL, wxID_ANY, wxDefaultPosition, wxDefaultSize,
10            wxSIMPLE_BORDER|wxSTAY_ON_TOP);
11
12    Yield(); // 挂起消息
13
14         Sleep( 2000 );
15
16        delete splashScreen;

这样,程序在每次运行前,都会在先屏幕中央弹出splash.png这张图片,2秒终后,出现程序界面。。

版权声明:本篇为原创文章,允许转载,但转载时请务必以超链接形式标明文章的原始出处和作者信息。请尊重本人的劳动成果,谢谢!
小祥的BLOG http://xfxsworld.cnblogs.com
posted @ 2008-01-26 21:45 小祥 阅读(557) | 评论 (0)编辑

2007年11月17日

                               vs2005环境下CELayoutEditor源码编译详细步骤

今天初试了一下CEGUI的官方编辑器——CELayoutEditor,其过程真可谓“饱受挫折”。现简要写下其源码的编译过程,已使可能会用到的朋友少走些弯路

1.    要编译CELayoutEditor,自然需要先编译CEGUI的东东,有2种选择:
        1.1 安装SDK,这是下载地址:http://jaist.dl.sourceforge.net/sourceforge/crayzedsgui/CEGUI-SDK-0.5.0b-vc8.exe,不过并不推荐这种方法,因为SDK里的debug版dll似乎有问题。。。
        1.2 编译其源代码。下载地址:http://jaist.dl.sourceforge.net/sourceforge/crayzedsgui/CEGUI-0.5.0b.zip,另外还需要下载依赖文件包dependencies package ,下载地址是:http://jaist.dl.sourceforge.net/sourceforge/crayzedsgui/CEGUI-DEPS-0.5.0b-vc8.zip,然后将依赖文件解压进源代码文件夹就OK了。
                  1.2.1   先别急着找solution,有个地方需要注意。CEGUI默认的是OPENGL渲染,如果是用D3D的话还得改一个地方。进..\makefiles\premake文件夹找到config.lua文件,记事本打开。改成“OPENGL_RENDERER = false,DIRECTX9_RENDERER = true”,保存就可以了。CELayoutEditor是用OPENGL的,所以这里不做任何改动。
                  1.2.2    运行build_vs2005.bat文件,执行完毕后会生成CEGUI.sln文件,打开就可直接编译了
         1.3   建立环境变量:我的电脑\属性\高级\环境变量,然后在上面的用户变量区新建一个,变量名是CEGUI,变量值是CEGUI的解压目录。注意这步不能省


2    由于CELayoutEditor使用了wxWidgets,所以在编译CELayoutEditor之前还需要下载wxWidgets。目前最新版本是2.86,进入官方下载网页http://www.wxwidgets.org/downloads/ 选择WxAll下载。
        2.1 建立环境变量:我的电脑\属性\高级\环境变量,然后在上面的用户变量区新建一个,变量名是WXWIDGETS,变量值是wxWidgets的解压目录。
        2.2  进wxWidgets的解压目录找到wx.dsw,打开、“Yes To All”转换。转换完毕后先别编译,还需要改下。因为wxWidgets默认并不是OPENGL
Open $(WXWIDGETS)\include\wx\msw\setup.h and replace 

Code: 
#define wxUSE_GLCANVAS 0  
WITH Code: 
#define wxUSE_GLCANVAS 1 


7.2 Open $(WXWIDGETS)\include\wx\univ\setup.h and replace 

Code: 
#if defined(__WIN32__) 
   
#define wxUSE_GLCANVAS 1 
else    
    
#define wxUSE_GLCANVAS 0 

WITH 
Code: 
#define wxUSE_GLCANVAS 1 


           2.3    现在就可以开始编译了。注意要选择“Unicode Debug”和“'Unicode Release”方式

3          下载CELayoutEditor。我是用SVN接的,地址是 https://crayzedsgui.svn.sourceforge.net/svnroot/crayzedsgui/CELayoutEditor/trunk
            3.1    解压后打开工程,将Include和Lib路径改成自己的,其他的不用改
            3.2    建立环境变量:我的电脑\属性\高级\环境变量,然后在上面的用户变量区新建一个,变量名是CE_LAYOUT_EDITOR ,变量值是CELayoutEditor的解压目录。注意这步不能省
            3.3    终于可以开始编译了。。。

4          
            4.1    编译会出现一个错误,暂时我还没找到解决方法,仅仅是给错误的地方注释掉了。。。然后就编译成功了
            4.2    拷一些东西过来

TO $(CE_LAYOUT_EDITOR)\bin\debug (Debug configuration) 
- CEGUIBase_d.dll 
- CEGUIExpatParser_d.dll 
- CEGUIFalagardWRBase_d.dll 
- CEGUISILLYImageCodec_d.dll 
- CEGUITGAImageCodec_d.dll 
- OpenGLGUIRenderer_d.dll 
- SILLY_d.dll

TO $(CE_LAYOUT_EDITOR)\bin\release (Release configuration) 
- CEGUIBase.dll 
- CEGUIExpatParser.dll 
- CEGUIFalagardWRBase.dll 
- CEGUISILLYImageCodec.dll 
- CEGUITGAImageCodec.dll 
- OpenGLGUIRenderer.dll
- SILLY.dll

           4.3 SILLY.dll和SILLY_d.dll在依赖文件夹里

OK。。。到这里就完了,虽然这个工具的bug很多,不过不怕,编译它就是为了要改造它,呵呵。希望此文对你有所帮助

开启画面




运行界面


版权声明
:本篇为原创文章,允许转载,但转载时请务必以超链接形式标明文章的原始出处和作者信息。请尊重本人的劳动成果,谢谢!
小祥的BLOG http://xfxsworld.cnblogs.com

 

posted @ 2007-11-17 14:59 小祥 阅读(1293) | 评论 (6)编辑