fs再次重构心得

1 篇文章 0 订阅

      经过一段时间以后的沉淀,对于代码的坏味道的识别能力也渐渐增强。发觉在做开发过程中有一些基础的东西还是很难改变,其中 对缓冲区设计 感觉尤为重要,内存缓冲区,线程池,通信队列等等。有时间一定要好好研究一下缓冲区的设计,现在就让我来记录本次重构遇到的一些问题。

 

1:链接器到底是如何工作的呢?

     在我的项目程序中,程序被分成好几个模块,模块之间有相互作用,为了减少依赖,尽量让文件独立,但是有一个很奇怪的问题是:

     比如两个模块分别取名为A, B. B模块的某头文件中引用了一个A模块的一个文件声明IDocument。

     如果定义成 对象的形式就会出现链接错误,

     CThreadManager<CartoonItem<IDocument>, CDownloadThread<CartoonItem<IDocument>>> m_cartoonTM;

     而定义成指针形式就OK.

     CThreadManager<CartoonItem<IDocument>, CDownloadThread<CartoonItem<IDocument>>> * m_pCartoonTM;

     这到底是为什么呢?

     后来重新Build了一下模块,发现不管是指针还是对象,其实都是有链接错误。之所以会出现上述那么奇怪的问题,我想是因为改动太大,由于编译的的增量编译特性导致原 

     有生成的文件没有被更新。

     后来最后修改的的方法就是抛弃IDocument的依赖。

 

2:STL的 find_if, count_if, mem_fun,  mem_fun_ref, bind2nd, 方法.

      可以参见 http://topic.csdn.net/u/20081107/13/8cce2bcb-9ec6-4d65-8404-3424d4746b6b.html; 然后根据这例子代码去查看相关代码的实现,

      mem_fun 要求容器存放的是指针,

      _Result operator()(const _Ty *_Pleft, _Arg _Right) const
      { // call function with operand
          return ((_Pleft->*_Pmemfun)(_Right)); // _Pleft就是迭代器,也就是容器存放的数据类型。
      }

     所以如果你的容器假设是 class CTest ; vector<CTest> vec; 就不能这样使用了。换成 mem_fun_ref 就可以了。

 

3:有时候你需要处理很多不同类型的数据,但是又像使用同一个容器,一个容器可以满足不同数据类型存放嘛?好像以前在C++ 沉思录里面看到过,有时间再拿出来翻翻。

待续!

 

4:在使用FlashDevelop用AS3来加载AS2资源的时候,当调用addChild的时候会出现如下错误

[Fault] exception, information=ArgumentError: Error #2180: 如果 AVM1 内容(AS1 或 AS2)已加载到 AVM2 (AS3) 内容中,则不可将其移动到 displayList 的其他部分。

修改的方法就是在Project窗口, 选中当前工程-》properties->Output 选项卡--》Platform, Flash Player 改成9.00就可以避免该问题了.

 

5:当在FlashDevelop工程Output中用Flash Player 9.00 Platform来输出文件时,利用Embed(source="../../../../res/assemble_down.PNG")]  private var downIcon:Class;方式来实现贴图按钮时却又遇到如下问题:

[Fault] exception, information=VerifyError: Error #1053: 在 mx.core.BitmapAsset 中非法覆盖 z。

查了很多资料,都是说要要将 Output中用Flash Player 9.00 Platform 修改为 Output中用Flash Player 10.0.测试发现是可以,但是这与上面的的情况就很尴尬了,因为服务器

上面已经 有很多AS2发布的资源,不能去将所有的资源都修改成AS3的吧,而且还要考虑版本兼容性问题,最后只好放弃以上实现方式,自己编写代码来实现贴图。方法很简单。

   加载资源:

 

package UI
{
	import flash.display.Loader;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.net.URLRequest;
	public class Icon extends Sprite
	{
		public function Icon(res:String)
		{
			var ul:URLRequest = new URLRequest(res);
			var loader:Loader = new Loader();
			loader.contentLoaderInfo.addEventListener(Event.COMPLETE, CompleteResLoad);
			loader.load(ul);
		}
	
		private function CompleteResLoad(e:Event):void
		{
			var disObj:DisplayObject = e.currentTarget.content as DisplayObject;
			var bmpData:BitmapData = new BitmapData(disObj.width, disObj.height, false);
			bmpData.draw(disObj);		
			var bmp:Bitmap = new Bitmap(bmpData);
			addChild(bmp);
		}
	}
}

6: c++与AS通信的方式?

    首先C++加载Shockwave  Flash控件,然后通过CallFunction函数,按照Flash规定的格式,向对方传递注册函数及参数,<invoke name>后面的名字就好比是注册函数,AS3必须要用 ExternalInterface.addCallback("ContainCallFunc", ResponseFunc); 对应,ResponseFunc就是AS3的响应函数。也就是说当C++调用CallFunction函数时,

AS3就用ResponseFunc来处理C++传递过来的参数,如果AS3有需要信息需要回传给C++的话,有两种方式: ExternalInterface.call 和 fscommand, c++接受的参数形式会因

因调用方式不同而不同。

C++代码如下

CShockwaveflash1 flashUI;

BOOL CInterActionDlg::OnInitDialog()
{
 std::string fileName = "D:\\FlashPrj\\Test\\IconControl\\bin\\IconControl.swf";
 flashUI.LoadMovie(0, fileName.c_str());
}

void CInterActionDlg::OnBnClickedOk()
{
 //*as3.0 写法: <arguments><string>****</string></arguments> 必须写在一行
 this->flashUI.CallFunction("<invoke name=\"ContainCallFunc\">\
           <arguments><string>c++1调用flash</string></arguments>\
   </invoke>");  
 //*/
 /*as2.0 写法:
 this->flashUI.CallFunction(L"<invoke name=\"ContainCallFunc\">\
         <arguments>\
          <string>c++调用flash</string>\
         </arguments>\
        </invoke>"); 
 //*/
}

BEGIN_EVENTSINK_MAP(CInterActionDlg, CDialog)
 ON_EVENT(CInterActionDlg, IDC_SHOCKWAVEFLASH1, 150/*fscommand*/, CInterActionDlg::FSCommandShockwaveflash1, VTS_BSTR VTS_BSTR)
 ON_EVENT(CInterActionDlg, IDC_SHOCKWAVEFLASH1, 197/*ExternalInterface.call*/, CInterActionDlg::ASCallback, VTS_BSTR)
END_EVENTSINK_MAP()

void CInterActionDlg::FSCommandShockwaveflash1(LPCTSTR command,  LPCTSTR args)
{
 if(0 == strcmp(command, "MsgBox"))
  MessageBox(args);
}

void CInterActionDlg::ASCallback(LPCTSTR request)
{
 MessageBox(request);
}


AS3代码如下:

private function init(e:Event = null):void 
  {
   removeEventListener(Event.ADDED_TO_STAGE, init);
   // entry point 
   if (ExternalInterface.available)
   {
    ExternalInterface.addCallback("ContainCallFunc", ResponseFunc);
   }
  }  
  
  private function ResponseFunc(strCode:String):void 
  {
   //*
   var mcw = new MaskContainWnd();
   this.stage.addChild(mcw);  
   //*/
   // fscommand("MsgBox", "haohao");
   ExternalInterface.call("ASCallback", "fddfd");
  }

7: 显示比例错误,怎么办?

在使用C++去加载AS3的代码是,发现最后显示的结果比例不协调,最后发现,原来跟C++利用shockwave的属性有关。注意Slign, Scale, ScalMode的取值。

 

   8:AS3不提供枚举类型,以下形式代码可以用来代替。

package net.smilecn.LibAndMCBind
{
	/**
	 * ...
	 * @author Zander
	 */
	public final class FSEnum
	{
		public static const TASKTYPE_NONEREGISTER:int = 0;
		public static const TASKTYPE_AVATAR:int = 1;
		public static const TASKTYPE_FASHION:int = 2;
		public static const TASKTYPE_3D:int = 3;
		public static const TASKTYPE_CUSTOMPHOTO:int = 4;
		public static const TASKTYPE_ADV:int = 5;
		public static const TASKTYPE_EM:int = 6;
		public static const TASKTYPE_ERROR:int = 7;
		public static const TASKTYPE_UNKNOWN:int = 8;
	}
}

 

9:BitmapData的缺省函数不是按你所想的那样工作。

在做界面显示的时候,由于这个类的缺省构造函数是透明的,也就真以为是透明的,查看adobe Flash CS3帮助说明才明白,

摘自adobe Flash CS3帮助文档:

     transparent:Boolean (default =true) — 指定位图图像是否支持每个像素具有不同的透明度。 默认值为 true(透明)。若要创建完全透明的位图,请将  

  transparent 参数的值设置为 true,将 fillColor 参数的值设置为 0x00000000(或设置为 0)。

 

10: stopPropagation() 与 stopImmediatePropagation() 函数对事件处理的优化。

如果有多个窗口是父子关系,为了只让子窗口的消息不透传至父窗口上去,需要对时间进行屏蔽,你需要调用stopPropagation() 函数,也许你也这样做了,但是最后发现

结果还是传给父窗口上去了,那是因为子窗口的其他消息你没有调用stopPropagation()函数导致的。有时父子窗口在焦点获取的时候会激发一些消息事件。他们的事件关系

就好比如下图所示:


所以如果子窗口需要将消息向父窗口进行屏蔽,需要将所有相关的消息统统写上,然后在消息最后写上stopPropagation()函数。stopImmediatePropagation()没尝试过。

对于鼠标类的消息,还有一种粗粒度的方法就是调用 sprite 的 mouseEnable 属性。


11: 多次调用Flash Shockwave控件的 CallFunction 的时候出现 _com_error 异常的原因?

×):检查同一个swf播放器是否多次加载。如:raw_LoadMovie 是否多次调用。

×):检查显示在swf播放器的内容是否在AS端调用了 removeChild .破坏swf播放器的显示。

×):检查第二次调用CallFunction之前AS端是否取消了监听响应( 即:ExterInterface.Callback 第二个参数设置为 null.)

 

12:线程结束

工作线程

Handler hWorkThread =  _beginthreadex(***);

_endthreadex(0);

等待线程

WaitForSingleObject(hWorkThread, INFINIET);

CloseHandle( hWorkThread);

所以就可以用

       WaitForSingleObject(hWorkThread, INFINIET)==WAIT_OBJECT_0; 来判断一个线程是否结束,

       线程的有无信号可以通过 beginthreadex, endthreadex 来获知。

 

以下摘自MSDN代码:

// crt_begthrdex.cpp
// compile with: /MT
#include <windows.h>
#include <stdio.h>
#include <process.h>

unsigned Counter; 
unsigned __stdcall SecondThreadFunc( void* pArguments )
{
    printf( "In second thread...\n" );

    while ( Counter < 1000000 )
        Counter++;

    _endthreadex( 0 );
    return 0;
} 

int main()
{ 
    HANDLE hThread;
    unsigned threadID;

    printf( "Creating second thread...\n" );

    // Create the second thread.
    hThread = (HANDLE)_beginthreadex( NULL, 0, &SecondThreadFunc, NULL, 0, &threadID );

    // Wait until second thread terminates. If you comment out the line
    // below, Counter will not be correct because the thread has not
    // terminated, and Counter most likely has not been incremented to
    // 1000000 yet.
    WaitForSingleObject( hThread, INFINITE );
    printf( "Counter should be 1000000; it is-> %d\n", Counter );
    // Destroy the thread object.
    CloseHandle( hThread );
}


 

 

问题:

1:问题?

*)为什么这样做会有问题?

 //TCHAR** pResArray = new TCHAR*[5];
 //wmemset(pResArray[0], 0, 5);
 //wmemcpy(pResArray[0], L"ssss", 5);

*) 注意版本,数据类型

/*
  wstringstream ss;
  BYTE* sb = new BYTE[5];
  memset(sb, 0, 5);
  memcpy(sb, "0123", 5);
  ss<<sb; //输出:003bc078
  //*/
  /*
  wstringstream ss;
  TCHAR* sb = new TCHAR[5];
  wmemset(sb, 0, 5);
  wmemcpy(sb, L"0123", 5);
  ss<<sb; //输出:0123
  //*/
  stringstream ss;
  BYTE* sb = new BYTE[5];
  memset(sb, 0, 5);
  memcpy(sb, "0123", 5);
  ss<<sb;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值