WinNing's profile无限&思想BlogListsGuestbook Tools Help

Blog


    October 24

    lockon操作键盘

    飞行控制:
    ↑ :飞机拉起
    ↓ :飞机压低
    ← :向左翻滚
    → :向右翻滚
    Z:左舵(空中),左转(地面)
    X:右舵(空中),右转(地面)
    A:自动驾驶
    H:打开/取消高度固定
    J:打开/取消速度固定
    Shift+N:重置语音警报
    K:解除仰角抑制(执行“眼镜蛇”机动)
    U:在航母上进入起飞位置
    Ctrl+. :向上配平
    Ctrl+; :向下配平
    Ctrl+, :向左配平
    Ctrl+/ :向右配平
    Ctrl+T:取消配平
    Ctrl+Z:左舵配平
    Ctrl+X:右舵配平

    机械系统控制:
    B:打开/关闭减速板
    F:打开/关闭襟翼
    G:打开/关闭起落架
    E: 打开/关闭电子干扰
    P:释放阻力伞
    W:机轮刹车(保持键)
    T:拉烟开关
    R:受油管伸缩开关
    L:仪表照明开关
    Ctrl+L:机身信号灯开关
    Alt+L:起落架灯--近光/远光/关闭
    Ctrl+EEE:弹射跳伞
    Ctrl+C:座舱盖开关
    Ctrl+G:打开/关闭尾勾(仅限SU33)
    Ctrl+P:机翼折叠开关(仅限SU33)
    Ctrl+R:空中释放燃油/地面加油(保持键)
    Alt+R:抛弃副油箱
    Ctrl+H:改变HUD颜色

    引擎控制:
    Page up:发动引擎/快速增加推力
    Page Down:关闭引擎/快速减小推力
    With Alt:ALT组合单纯控制左引擎
    With Shift:SHIFT组合单纯控制右引擎

    导航模式:
    ~ :选择下一导航点或机场
    1 :导航模式
    Alt+C:重置飞行时钟

    作战模式:
    2 :超视距空战模式
    3 :近距空战――垂直扫描模式
    4 :近距空战――孔径模式
    5 :近距空战――头盔模式
    6 :径向瞄准模式
    7 :空对地模式
    8 :目视投弹模式
    ~ :目标循环切换
    Tab:锁定所选目标或目标点(打开目标跟踪)
    Ctrl+Tab:关闭目标跟踪

    武器系统:
    D:武器选择
    C:机炮选择
    Q:释放干扰弹(单发释放)
    Shift+Q:释放干扰弹(连续释放)
    Enter:发射导弹
    Spacebar:发射机炮
    Ctrl+W:成对抛弃武器(空中),重新装填武器(地面)
    Ctrl+V:齐射模式开关
    Shift+C:改变机炮射速(A10)
    Shift+V:减小投弹间距(A10)
    Ctrl+Space:改变投弹数量(A10)
    Alt+Space:选择首选武器(A10)
    Shift+Space:单个/成对投弹模式切换(A10)

    雷达光电系统:
    I:雷达开关
    Alt+I:RWS/TWS(目标跟踪)雷达模式切换(仅限于F-15)
    O:俄战斗机:打开/关闭光电扫描仪
         俄攻击机:打开/关闭激光测距仪
         美攻击机:打开/关闭CCRP投弹模式
    Ctrl+I:所有扫描仪器归中
    - :扩大MFD显示范围
    + :减小MFD显示范围
    Ctrl++ :增大F15雷达天线方位角
    Ctrl+- :减小F15雷达天线方位角

    空对空模式:
    Shift+; :向上移动雷达/光电扫描区
    Shift+, :向左移动雷达/光电扫描区
    Shift+. :向下移动雷达/光电扫描区
    Shift+/ :向右移动雷达/光电扫描区

    空对地模式:
    Shift+; :雷达/电视制导探头上移
    Shift+, :雷达/电视制导探头左移
    Shift+. :雷达/电视制导探头下移
    Shift+/ :雷达/电视制导探头右移

    视角选择:
    F1:座舱视角
    F2:外部视角
    F3:飞越视角
    F4:后视视角
    Ctrl+F4:追尾视角
    F5:空战视角
    F6:武器视角
    F7:活动的地面物体视角
    F8:目标视角
    F9:舰船视角
    F10:地图视角
    F11:塔台及地表视角
    F12:静态物体视角

    座舱视角控制:
    Key Pad 1:视角向左下移动
    Key Pad 2:视角向下移动
    Key Pad 3:视角向右下移动
    Key Pad 4:视角向左移动
    Key Pad 5:视角归中
    Key Pad 6:视角向右移动
    Key Pad 7:视角向左上移动
    Key Pad 8:视角向上移动
    Key Pad 9:视角向右上移动
    Key Pad 0:仪表盘视角切换(保持键)
    Key Pad 1+5:HUD视角
    Key Pad * :向前移动视点
    Key Pad / :向后移动视点
    Key Pad Del:目视锁定
    Key Pad NumLock:取消目视锁定
    M:右后视镜视角
    N:左后视镜视角

    程序控制:
    Esc:退出任务/录相
    Ctrl+Q:在播放录相时控制飞机
    Alt+J:取得/放弃所选飞机控制权
    Ctrl+A:加快游戏速度(快镜头)
    Alt+A:减慢游戏速度(慢镜头)
    Shift+A:恢复正常游戏速度
    S:任务开始/暂停/继续
    ‘ :单人任务时显示任务目标窗口/联网任务时显示成绩窗口
    Ctrl+M:联网任务时打开对话窗口――向所有玩家发送信息
    Alt+M:联网任务时打开对话窗口――向己方玩家发送信息

    July 05

    VC

    VC字符串转换(附数据类型转换)

    一、BSTR、LPSTR和LPWSTR
    在Visual C++.NET的所有编程方式中,我们常常要用到这样的一些基本字符串类型,如BSTR、LPSTR和LPWSTR等。之所以出现类似上述的这些数据类 型,是因为不同编程语言之间的数据交换以及对ANSI、Unicode和多字节字符集(MBCS)的支持。

      那么什么是BSTR、LPSTR以及LPWSTR呢?

       BSTR(Basic STRing,Basic字符串)是一个OLECHAR*类型的Unicode字符串。它被描述成一个与自动化相兼容的类型。由于操作系统提供相应的 API函数(如SysAllocString)来管理它以及一些默认的调度代码,因此BSTR实际上就是一个COM字符串,但它却在自动化技术以外的多种 场合下得到广泛使用。图1描述了BSTR的结构,其中DWORD值是字符串中实际所占用的字节数,且它的值是字符串中Unicode字符的两倍。

       LPSTR和LPWSTR是Win32和VC++所使用的一种字符串数据类型。LPSTR被定义成是一个指向以NULL(‘\0’)结尾的8位ANSI 字符数组指针,而LPWSTR是一个指向以NULL结尾的16位双字节字符数组指针。在VC++中,还有类似的字符串类型,如LPTSTR、 LPCTSTR等,它们的含义如图2所示。

      例如,LPCTSTR是指“long pointer to a constant generic string”,表示“一个指向一般字符串常量的长指针类型”,与C/C++的const char*相映射,而LPTSTR映射为 char*。

      一般地,还有下列类型定义:

    #ifdef UNICODE
    typedef LPWSTR LPTSTR;
    typedef LPCWSTR LPCTSTR;
    #else
    typedef LPSTR LPTSTR;
    typedef LPCSTR LPCTSTR;
    #endif

    二、CString、CStringA 和 CStringW

       Visual C++.NET中将CStringT作为ATL和MFC的共享的“一般”字符串类,它有CString、CStringA和CStringW三种形式,分 别操作不同字符类型的字符串。这些字符类型是TCHAR、char和wchar_t。TCHAR在Unicode平台中等同于WCHAR(16位 Unicode字符),在ANSI中等价于char。wchar_t通常定义为unsigned short。由于CString在MFC应用程序中经常用到,这里不再重复。

    三、VARIANT、COleVariant 和_variant_t

      在OLE、ActiveX和COM中,VARIANT数据类型提供了一种非常有效的机制,由于它既包含了数据本身,也包含了数据的类型,因而它可以实现各种不同的自动化数据的传输。下面让我们来看看OAIDL.H文件中VARIANT定义的一个简化版:

    struct tagVARIANT {
    VARTYPE vt;
    union {
    short iVal; // VT_I2.
    long lVal; // VT_I4.
    float fltVal; // VT_R4.
    double dblVal; // VT_R8.
    DATE date; // VT_DATE.
    BSTR bstrVal; // VT_BSTR.

    short * piVal; // VT_BYREF|VT_I2.
    long * plVal; // VT_BYREF|VT_I4.
    float * pfltVal; // VT_BYREF|VT_R4.
    double * pdblVal; // VT_BYREF|VT_R8.
    DATE * pdate; // VT_BYREF|VT_DATE.
    BSTR * pbstrVal; // VT_BYREF|VT_BSTR.
    };
    };

      显然,VARIANT类型是一个C结构,它包含了一个类型成员vt、一些保留字节以及一个大的union类型。例如,如果vt为VT_I2,那么我们可以从iVal中读出VARIANT的值。同样,当给一个VARIANT变量赋值时,也要先指明其类型。例如:

    VARIANT va;
    :: VariantInit(&va); // 初始化
    int a = 2002;
    va.vt = VT_I4; // 指明long数据类型
    va.lVal = a; // 赋值

      为了方便处理VARIANT类型的变量,Windows还提供了这样一些非常有用的函数:

      VariantInit —— 将变量初始化为VT_EMPTY;

      VariantClear —— 消除并初始化VARIANT;

      VariantChangeType —— 改变VARIANT的类型;

      VariantCopy —— 释放与目标VARIANT相连的内存并复制源VARIANT。

       COleVariant类是对VARIANT结构的封装。它的构造函数具有极为强大大的功能,当对象构造时首先调用VariantInit进行初始化, 然后根据参数中的标准类型调用相应的构造函数,并使用VariantCopy进行转换赋值操作,当VARIANT对象不在有效范围时,它的析构函数就会被 自动调用,由于析构函数调用了VariantClear,因而相应的内存就会被自动清除。除此之外,COleVariant的赋值操作符在与 VARIANT类型转换中为我们提供极大的方便。例如下面的代码:

    COleVariant v1("This is a test"); // 直接构造
    COleVariant v2 = "This is a test";
    // 结果是VT_BSTR类型,值为"This is a test"
    COleVariant v3((long)2002);
    COleVariant v4 = (long)2002;
    // 结果是VT_I4类型,值为2002

      _variant_t是一个用于COM的VARIANT类,它的功能与COleVariant相似。不过在Visual C++.NET的MFC应用程序中使用时需要在代码文件前面添加下列两句:

      #include "comutil.h"

      #pragma comment( lib, "comsupp.lib" )

    四、CComBSTR和_bstr_t

      CComBSTR是对BSTR数据类型封装的一个ATL类,它的操作比较方便。例如:

    CComBSTR bstr1;
    bstr1 = "Bye"; // 直接赋值
    OLECHAR* str = OLESTR("ta ta"); // 长度为5的宽字符
    CComBSTR bstr2(wcslen(str)); // 定义长度为5
    wcscpy(bstr2.m_str, str); // 将宽字符串复制到BSTR中
    CComBSTR bstr3(5, OLESTR("Hello World"));
    CComBSTR bstr4(5, "Hello World");
    CComBSTR bstr5(OLESTR("Hey there"));
    CComBSTR bstr6("Hey there");
    CComBSTR bstr7(bstr6);
    // 构造时复制,内容为"Hey there"

      _bstr_t是是C++对BSTR的封装,它的构造和析构函数分别调用SysAllocString和SysFreeString函数,其他操作是借用BSTR API函数。与_variant_t相似,使用时也要添加comutil.h和comsupp.lib。

    五、BSTR、char*和CString转换

      (1) char*转换成CString

      若将char*转换成CString,除了直接赋值外,还可使用CString::Format进行。例如:

    char chArray[] = "This is a test";
    char * p = "This is a test";

      或

    LPSTR p = "This is a test";

      或在已定义Unicode应的用程序中

    TCHAR * p = _T("This is a test");

      或

    LPTSTR p = _T("This is a test");
    CString theString = chArray;
    theString.Format(_T("%s"), chArray);
    theString = p;

      (2) CString转换成char*

      若将CString类转换成char*(LPSTR)类型,常常使用下列三种方法:

      方法一,使用强制转换。例如:

    CString theString( "This is a test" );
    LPTSTR lpsz =(LPTSTR)(LPCTSTR)theString;

      方法二,使用strcpy。例如:

    CString theString( "This is a test" );
    LPTSTR lpsz = new TCHAR[theString.GetLength()+1];
    _tcscpy(lpsz, theString);

      需要说明的是,strcpy(或可移值Unicode/MBCS的_tcscpy)的第二个参数是 const wchar_t* (Unicode)或const char* (ANSI),系统编译器将会自动对其进行转换。

      方法三,使用CString::GetBuffer。例如:

    CString s(_T("This is a test "));
    LPTSTR p = s.GetBuffer();
    // 在这里添加使用p的代码
    if(p != NULL) *p = _T('\0');
    s.ReleaseBuffer();
    // 使用完后及时释放,以便能使用其它的CString成员函数

      (3) BSTR转换成char*

      方法一,使用ConvertBSTRToString。例如:

    #include
    #pragma comment(lib, "comsupp.lib")
    int _tmain(int argc, _TCHAR* argv[]){
    BSTR bstrText = ::SysAllocString(L"Test");
    char* lpszText2 = _com_util::ConvertBSTRToString(bstrText);
    SysFreeString(bstrText); // 用完释放
    delete[] lpszText2;
    return 0;
    }

      方法二,使用_bstr_t的赋值运算符重载。例如:

    _bstr_t b = bstrText;
    char* lpszText2 = b;

      (4) char*转换成BSTR

      方法一,使用SysAllocString等API函数。例如:

    BSTR bstrText = ::SysAllocString(L"Test");
    BSTR bstrText = ::SysAllocStringLen(L"Test",4);
    BSTR bstrText = ::SysAllocStringByteLen("Test",4);

      方法二,使用COleVariant或_variant_t。例如:

    //COleVariant strVar("This is a test");
    _variant_t strVar("This is a test");
    BSTR bstrText = strVar.bstrVal;

      方法三,使用_bstr_t,这是一种最简单的方法。例如:

    BSTR bstrText = _bstr_t("This is a test");

      方法四,使用CComBSTR。例如:

    BSTR bstrText = CComBSTR("This is a test");

      或

    CComBSTR bstr("This is a test");
    BSTR bstrText = bstr.m_str;

      方法五,使用ConvertStringToBSTR。例如:

    char* lpszText = "Test";
    BSTR bstrText = _com_util::ConvertStringToBSTR(lpszText);

      (5) CString转换成BSTR

      通常是通过使用CStringT::AllocSysString来实现。例如:

    CString str("This is a test");
    BSTR bstrText = str.AllocSysString();

    SysFreeString(bstrText); // 用完释放

      (6) BSTR转换成CString

      一般可按下列方法进行:

    BSTR bstrText = ::SysAllocString(L"Test");
    CStringA str;
    str.Empty();
    str = bstrText;

      或

    CStringA str(bstrText);

      (7) ANSI、Unicode和宽字符之间的转换

      方法一,使用MultiByteToWideChar将ANSI字符转换成Unicode字符,使用WideCharToMultiByte将Unicode字符转换成ANSI字符。

      方法二,使用“_T”将ANSI转换成“一般”类型字符串,使用“L”将ANSI转换成Unicode,而在托管C++环境中还可使用S将ANSI字符串转换成String*对象。例如:

    TCHAR tstr[] = _T("this is a test");
    wchar_t wszStr[] = L"This is a test";
    String* str = S”This is a test”;

      方法三,使用ATL 7.0的转换宏和类。ATL7.0在原有3.0基础上完善和增加了许多字符串转换宏以及提供相应的类,它具有如图3所示的统一形式:

       其中,第一个C表示“类”,以便于ATL 3.0宏相区别,第二个C表示常量,2表示“to”,EX表示要开辟一定大小的缓冲。SourceType和DestinationType可以是A、 T、W和OLE,其含义分别是ANSI、Unicode、“一般”类型和OLE字符串。例如,CA2CT就是将ANSI转换成一般类型的字符串常量。下面 是一些示例代码:

    LPTSTR tstr= CA2TEX<16>("this is a test");
    LPCTSTR tcstr= CA2CT("this is a test");
    wchar_t wszStr[] = L"This is a test";
    char* chstr = CW2A(wszStr);

    另附前文 数据类型转换以参考

    我们先定义一些常见类型变量借以说明

    int i = 100;
    long l = 2001;
    float f=300.2;
    double d=12345.119;
    char username[]="女侠程佩君";
    char temp[200];
    char *buf;
    CString str;
    _variant_t v1;
    _bstr_t v2;

    一、其它数据类型转换为字符串

    短整型(int)
    itoa(i,temp,10);///将i转换为字符串放入temp中,最后一个数字表示十进制
    itoa(i,temp,2); ///按二进制方式转换
    长整型(long)
    ltoa(l,temp,10);

    二、从其它包含字符串的变量中获取指向该字符串的指针

    CString变量
    str = "2008北京奥运";
    buf = (LPSTR)(LPCTSTR)str;
    BSTR类型的_variant_t变量
    v1 = (_bstr_t)"程序员";
    buf = _com_util::ConvertBSTRToString((_bstr_t)v1);

    三、字符串转换为其它数据类型
    strcpy(temp,"123");

    短整型(int)
    i = atoi(temp);
    长整型(long)
    l = atol(temp);
    浮点(double)
    d = atof(temp);

    四、其它数据类型转换到CString
    使用CString的成员函数Format来转换,例如:

    整数(int)
    str.Format("%d",i);
    浮点数(float)
    str.Format("%f",i);
    字符串指针(char *)等已经被CString构造函数支持的数据类型可以直接赋值
    str = username;

    五、BSTR、_bstr_t与CComBSTR

    CComBSTR、_bstr_t是对BSTR的封装,BSTR是指向字符串的32位指针。
    char *转换到BSTR可以这样: BSTR b=_com_util::ConvertStringToBSTR("数据");///使用前需要加上头文件comutil.h
    反之可以使用char *p=_com_util::ConvertBSTRToString(b);

    六、VARIANT 、_variant_t 与 COleVariant

    VARIANT的结构可以参考头文件VC98\Include\OAIDL.H中关于结构体tagVARIANT的定义。
    对于VARIANT变量的赋值:首先给vt成员赋值,指明数据类型,再对联合结构中相同数据类型的变量赋值,举个例子:
    VARIANT va;
    int a=2001;
    va.vt=VT_I4;///指明整型数据
    va.lVal=a; ///赋值

    对于不马上赋值的VARIANT,最好先用Void VariantInit(VARIANTARG FAR* pvarg);进行初始化,其本质是将vt设置为VT_EMPTY,下表我们列举vt与常用数据的对应关系:

    unsigned char bVal; VT_UI1
    short iVal; VT_I2
    long lVal;  VT_I4 
    float fltVal;  VT_R4
    double dblVal;  VT_R8 
    VARIANT_BOOL boolVal;  VT_BOOL
    SCODE scode;  VT_ERROR
    CY cyVal;  VT_CY
    DATE date;  VT_DATE
    BSTR bstrVal;  VT_BSTR
    IUnknown FAR* punkVal;  VT_UNKNOWN
    IDispatch FAR* pdispVal;  VT_DISPATCH
    SAFEARRAY FAR* parray;  VT_ARRAY|*
    unsigned char FAR* pbVal;  VT_BYREF|VT_UI1
    short FAR* piVal;  VT_BYREF|VT_I2
    long FAR* plVal;  VT_BYREF|VT_I4
    float FAR* pfltVal;  VT_BYREF|VT_R4
    double FAR* pdblVal; VT_BYREF|VT_R8
    VARIANT_BOOL FAR* pboolVal; VT_BYREF|VT_BOOL
    SCODE FAR* pscode;  VT_BYREF|VT_ERROR
    CY FAR* pcyVal;  VT_BYREF|VT_CY
    DATE FAR* pdate; VT_BYREF|VT_DATE
    BSTR FAR* pbstrVal;  VT_BYREF|VT_BSTR
    IUnknown FAR* FAR* ppunkVal;  VT_BYREF|VT_UNKNOWN
    IDispatch FAR* FAR* ppdispVal; VT_BYREF|VT_DISPATCH
    SAFEARRAY FAR* F

     

     

     

    VC字符串转换处理(ZZ)

    1.头文件中要定义宏;

    #define  UNICODE
    #define  _UNICODE
    ////////////////////

    char   buf[128]; 
    memset(buf, 0, 128); 
    strcpy(buf, "你好"); 
    WCHAR  pCName[128]; 
    memset(pCName, 0,1 28); 
    MultiByteToWideChar(CP_THREAD_ACP, MB_USEGLYPHCHARS, buf, strlen(buf), pCName, 128); 至于WCHAR   转换到CHAR,则用 
    WideCharToMultiByte

    //////////////////////////

    2.char转换成wchar

    const  char  *pFilePathName  =  "c:\\aa.dll";
    int  nLen  =  strlen(pFilePathName)  +  1;
    int  nwLen  =  MultiByteToWideChar(CP_ACP,  0,  pFilePathName, nLen,  NULL,  0);

    TCHAR  lpszFile[256];
    MultiByteToWideChar(CP_ACP,  0,  pFilePathName,  nLen,  lpszFile, nwLen);
    3.wchar转换成char

    char  *pFilePathName;
    TCHAR  lpszFile[256];
    _tcscpy(lpszFile,  _T("c:\\aa.dll"));
    int  nLen  =  wcslen(wstr)+1;
    WideCharToMultiByte(CP_ACP,  0,  lpszFile,  nLen,  pFilePathName, 2*nLen,  NULL,  NULL); char*和CString转换
    CString 是一种很特殊的 C++ 对象,它里面包含了三个值:一个指向某个数据缓冲区的指针、一个是该缓冲中有效的字符记数(它是不可存取的,是位于
    CString 地址之下的一个隐藏区域)以及一个缓冲区长度。
    有效字符数的大小可以是从0到该缓冲最大长度值减1之间的任何数(因为字符串结尾有一个NULL字符)。字符记数和缓冲区长度被巧妙隐藏。

    (1) char*转换成CString
      若将char*转换成CString,除了直接赋值外,还可使用CString::Format进行。例如:

          char chArray[] = "Char  test";
          TCHAR * p = _T("Char  test");( 或?LPTSTR p = _T("Char  test");)
          CString theString = chArray;
          theString.Format(_T("%s"), chArray);
          theString = p;(2) CString转换成char*

      若将CString类转换成char*(LPSTR)类型,常常使用下列三种方法:

      方法一,使用强制转换。例如:

           CString theString( (_T("Char test "));
           LPTSTR lpsz =(LPTSTR)(LPCTSTR)theString;  方法二,使用strcpy。例如:

           CString theString( (_T("Char test "));
           LPTSTR lpsz = new TCHAR[theString.GetLength()+1];
           _tcscpy(lpsz, theString);       需要说明的是,strcpy(或可移值的_tcscpy)的第二个参数是 const wchar_t* (Unicode)或const char*(ANSI),系统编译器将会自动对其进行转换。

      方法三,使用CString::GetBuffer。
               如果你需要修改 CString 中的内容,它有一个特殊的方法可以使用,那就是 GetBuffer,它的作用是返回一个可写的缓冲指针。
               如果你只是打算修改字符或者截短字符串,例如:

      CString s(_T("Char test "));
      LPTSTR p = s.GetBuffer();
      LPTSTR dot = strchr(p, ''.'');
               // 在这里添加使用p的代码

      if(p != NULL)
      *p = _T('\0');
      s.ReleaseBuffer(); // 使用完后及时释放,以便能使用其它的CString成员函数  在 GetBuffer 和 ReleaseBuffer 之间这个范围,一定不能使用你要操作的这个缓冲的 CString 对象的任何方法。因为ReleaseBuffer 被调用之前,该 CString 对象的完整性得不到保障。 CString ,BSTR ,LPCTSTR之间关系和区别

    CString是一个动态TCHAR数组,BSTR是一种专有格式的字符串(需要用系统提供的函数来操纵,LPCTSTR只是一个常量的TCHAR指针。

    CString 是一个完全独立的类,动态的TCHAR数组,封装了 + 等操作符和字符串操作方法。

    typedef OLECHAR FAR* BSTR;
    typedef const char * LPCTSTR;vc++中各种字符串的表示法
    首先char*是指向ANSI字符数组的指针,其中每个字符占据8位(有效数据是除掉最高位的其他7位),这里保持了与传统的C,C++的兼容。
    LP的含义是长指针(long pointer)。LPSTR是一个指向以‘\0’结尾的ANSI字符数组的指针,与char*可以互换使用,在win32中较多地使用LPSTR。
    而LPCSTR中增加的‘C’的含义是“CONSTANT”(常量),表明这种数据类型的实例不能被使用它的API函数改变,除此之外,它与LPSTR是等同的。
    1.LP表示长指针,在win16下有长指针(LP)和短指针(P)的区别,而在win32下是没有区别的,都是32位.所以这里的LP和P是等价的.
    2.C表示const
    3.T是什么东西呢,我们知道TCHAR在采用Unicode方式编译时是wchar_t,在普通时编译成char.

    为了满足程序代码国际化的需要,业界推出了Unicode标准,它提供了一种简单和一致的表达字符串的方法,所有字符中的字节都是16位的值,其数量也可以满足差不多世界上所有书面语言字符的编码需求,开发程序时使用Unicode(类型为wchar_t)是一种被鼓励的做法。
    LPWSTR与LPCWSTR由此产生,它们的含义类似于LPSTR与LPCSTR,只是字符数据是16位的wchar_t而不是char。
    然后为了实现两种编码的通用,提出了TCHAR的定义:
    如果定义_UNICODE,声明如下:
    typedef wchar_t TCHAR;
    如果没有定义_UNICODE,则声明如下:
    typedef char TCHAR;
    LPTSTR和LPCTSTR中的含义就是每个字符是这样的TCHAR。
    CString类中的字符就是被声明为TCHAR类型的,它提供了一个封装好的类供用户方便地使用。

    LPCTSTR:
    #ifdef _UNICODE
    typedef const wchar_t * LPCTSTR;
    #else
    typedef const char * LPCTSTR;
    #endif
    VC常用数据类型使用转换详解
    先定义一些常见类型变量借以说明

    int i = 100;
    long l = 2001;
    float f=300.2;
    double d=12345.119;
    char username[]="木瓜";
    char temp[200];
    char *buf;
    CString str;
    _variant_t v1;
    _bstr_t v2;
    一、其它数据类型转换为字符串
    短整型(int)
    itoa(i,temp,10);
    //将i转换为字符串放入temp中,最后一个数字表示十进制
    itoa(i,temp,2);  //按二进制方式转换
    长整型(long)
    ltoa(l,temp,10);

    二、从其它包含字符串的变量中获取指向该字符串的指针
    CString变量
    str = "2008北京奥运";
    buf = (LPSTR)(LPCTSTR)str;
    BSTR类型的_variant_t变量
    v1 = (_bstr_t)"程序员";
    buf = _com_util::ConvertBSTRToString((_bstr_t)v1);
    三、字符串转换为其它数据类型
    strcpy(temp,"123");
    短整型(int)
    i = atoi(temp);
    长整型(long)
    l = atol(temp);
    浮点(double)
    d = atof(temp);
    四、其它数据类型转换到CString
    使用CString的成员函数Format来转换,例如:
    整数(int)
    str.Format("%d",i);
    浮点数(float)
    str.Format("%f",i);
    字符串指针(char *)等已经被CString构造函数支持的数据类型可以直接赋值
    str = username;
    五、BSTR、_bstr_t与CComBSTR
    CComBSTR、_bstr_t是对BSTR的封装,BSTR是指向字符串的32位指针。
    char *转换到BSTR可以这样: BSTR
    b=_com_util::ConvertStringToBSTR("数据");
    //使用前需要加上头文件comutil.h
    反之可以使用char *p=_com_util::ConvertBSTRToString(b);

    六、VARIANT 、_variant_t 与 COleVariant
    VARIANT的结构可以参考头文件VC98\Include\OAIDL.H中关于结构体tagVARIANT的定义。
    对于VARIANT变量的赋值:首先给vt成员赋值,指明数据类型,再对联合结构中相同数据类型的变量赋值,举个例子:

    VARIANT va;
    int a=2001;
    va.vt=VT_I4;  //指?明?整?型?数?据?
    va.lVal=a;  //赋?值?
    对于不马上赋值的VARIANT,最好先用Void VariantInit(VARIANTARG FAR*  pvarg);进行初始化,其本质是将vt设置为VT_EMPTY,下表我们列举vt与常用数据的对应关系:
    unsigned char bVal; VT_UI1
    short iVal; VT_I2
    long lVal;  VT_I4
    float fltVal;  VT_R4
    double dblVal;  VT_R8
    VARIANT_BOOL boolVal;  VT_BOOL
    SCODE scode;  VT_ERROR
    CY cyVal;  VT_CY
    DATE date;  VT_DATE
    BSTR bstrVal;  VT_BSTR
    IUnknown FAR* punkVal;  VT_UNKNOWN
    IDispatch FAR* pdispVal;  VT_DISPATCH
    SAFEARRAY FAR* parray;  VT_ARRAY|*
    unsigned char FAR* pbVal;  VT_BYREF|VT_UI1
    short FAR* piVal;  VT_BYREF|VT_I2
    long FAR* plVal;  VT_BYREF|VT_I4
    float FAR* pfltVal;  VT_BYREF|VT_R4
    double FAR* pdblVal; VT_BYREF|VT_R8
    VARIANT_BOOL FAR* pboolVal; VT_BYREF|VT_BOOL
    SCODE FAR* pscode;  VT_BYREF|VT_ERROR
    CY FAR* pcyVal;  VT_BYREF|VT_CY
    DATE FAR* pdate; VT_BYREF|VT_DATE
    BSTR FAR* pbstrVal;  VT_BYREF|VT_BSTR
    IUnknown FAR* FAR* ppunkVal;  VT_BYREF|VT_UNKNOWN
    IDispatch FAR* FAR* ppdispVal;
    VT_BYREF|VT_DISPATCH
    SAFEARRAY FAR* FAR* pparray;  VT_ARRAY|*
    VARIANT FAR* pvarVal;  VT_BYREF|VT_VARIANT
    void FAR* byref;  VT_BYREF

    _variant_t是VARIANT的封装类,其赋值可以使用强制类型转换,其构造函数会自动处理这些数据类型。
    例如:
    long l=222;
    int i=100;
    _variant_t lVal(l);
    lVal = (long)i;
    COleVariant的使用与_variant_t的方法基本一样,请参考如下例子:
    COleVariant v3 = "字符串", v4 = (long)1999;
    CString str =(BSTR)v3.pbstrVal;
    long i = v4.lVal;

    七、其它
    对消息的处理中我们经常需要将WPARAM或LPARAM等32位数据(DWORD)分解成两个16位数据(WORD),例如:
    对于16位的数据(WORD)我们可以用同样的方法分解成高低两个8位数据(BYTE),例如:
    WORD wValue;
    BYTE loValue = LOBYTE(wValue);  //取低8位
    BYTE hiValue = HIBYTE(wValue);  //取高8位

    如何将CString类型的变量赋给char*类型的变量
    1、GetBuffer函数:
    使用CString::GetBuffer函数。

    char *p;
    CString str="hello";
    p=str.GetBuffer(str.GetLength());
    str.ReleaseBuffer();将CString转换成char * 时

    CString str("aaaaaaa");
    strcpy(str.GetBuffer(10),"aa");
    str.ReleaseBuffer();当我们需要字符数组时调用GetBuffer(int  n),其中n为我们需要的字符数组的长度.使用完成后一定要马上调用ReleaseBuffer();还有很重要的一点就是,在能使用const char *的地方,就不要使用char *2、memcpy:CString mCS=_T("cxl");
    char mch[20];
    memcpy(mch,mCS,20);3、用LPCTSTR强制转换: 尽量不使用char *ch;
    CString str;
    ch=(LPSTR)(LPCTSTR)str;
    CString str = "good";
    char *tmp;
    sprintf(tmp,"%s",(LPTSTR)(LPCTSTR)str);
    4、
    CString Msg;
    Msg=Msg+"abc";
    LPTSTR lpsz;
    lpsz = new TCHAR[Msg.GetLength()+1];
    _tcscpy(lpsz, Msg);
    char * psz;
    strcpy(psz,lpsz);CString类向const char *转换
    char a[100];
    CString str("aaaaaa");
    strncpy(a,(LPCTSTR)str,sizeof(a));
    或者如下:
    strncpy(a,str,sizeof(a));
    以上两种用法都是正确地. 因为strncpy的第二个参数类型为const char *.所以编译器会自动将CString类转换成const char *.
    CString转LPCTSTR (const char *)
    CString cStr;
    const char *lpctStr=(LPCTSTR)cStr;
    LPCTSTR转CString
    LPCTSTR lpctStr;
    CString cStr=lpctStr;
    将char*类型的变量赋给CString型的变量
    可以直接赋值,如:
    CString myString = "This is a test";
    也可以利用构造函数,如:
    CString s1("Tom");
    将CString类型的变量赋给char []类型(字符串)的变量
    1、sprintf()函数
    CString str = "good";
    char tmp[200] ;
    sprintf(tmp, "%s",(LPCSTR)str);
    (LPCSTR)str这种强制转换相当于(LPTSTR)(LPCTSTR)str
    CString类的变量需要转换为(char*)的时,使用(LPTSTR)(LPCTSTR)str
    然而,LPCTSTR是const char *,也就是说,得到的字符串是不可写的!将其强制转换成LPTSTR去掉const,是极为危险的!
    一不留神就会完蛋!要得到char *,应该用GetBuffer()或GetBufferSetLength(),用完后再调用ReleaseBuffer()。
    2、strcpy()函数
    CString str;
    char c[256];
    strcpy(c, str);
    char mychar[1024];
    CString source="Hello";
    strcpy((char*)&mychar,(LPCTSTR)source);

    关于CString的使用
    1、指定 CString 形参
    对于大多数需要字符串参数的函数,最好将函数原型中的形参指定为一个指向字符 (LPCTSTR)
    而非 CString 的 const 指针。
    当将形参指定为指向字符的 const 指针时,可将指针传递到 TCHAR 数组(如字符串 ["hi
    there"])或传递到 CString 对象。
    CString 对象将自动转换成 LPCTSTR。任何能够使用 LPCTSTR 的地方也能够使用
    CString 对象。
    2、如果某个形参将不会被修改,则也将该参数指定为常数字符串引用(即 const CString&)。

    如果函数要修改该字符串,则删除 const 修饰符。如果需要默认为空值,则将其初始化为空字符串 [""],如下所示:
    void AddCustomer( const CString& name, const
    CString& address, const CString& comment = "" );
    3、对于大多数函数结果,按值返回 CString 对象即可。

    串的基本运算
    对于串的基本运算,很多高级语言均提供了相应的运算符或标准的库函数来实现。
    为叙述方便,先定义几个相关的变量:
    char s1[20]="dir/bin/appl", s2[20]="file.asm",s3[30],*p;
    int result;

    下面以C语言中串运算介绍串的基本运算
    1、求串长
    int strlen(char *s);  //求串s的长度
    【例】printf("%d",strlen(s1));  //输出s1的串长12
    2、串复制
    char *strcpy(char
    *to,*from);//将from串复制到to串中,并返回to开始处指针
    【例】strcpy(s3,s1);  //s3="dir/bin/appl",s1串不变

    3、联接
    char *strcat(char *to,char
    *from);//将from串复制到to串的末尾,
    //并返回to串开始处的指针
    【例】strcat(s3,"/");  //s3="dir/bin/appl/"
    strcat(s3,s2);
    //s3="dir/bin/appl/file.asm"
    4、串比较
    int strcmp(char *s1,char *s2);//比较s1和s2的大小,
    //当s1<s2、s1>s2和s1=s2时,分别返回小于0、大于0和等于0的值
    【例】result=strcmp("baker","Baker");
    //result>0
    result=strcmp("12","12");
    //result=0
    result=strcmp("Joe","joseph")
    //result<0
    5、字符定位
    char *strchr(char *s,char c);//找c在字符串s中第一次出现的位置,
    //若找到,则返回该位置,否则返回NULL
    【例】p=strchr(s2,'.');  //p指向"file"之后的位置
       if(p) strcpy(p,".cpp");  //s2="file.cpp"
    注意:
     ①上述操作是最基本的,其中后4个操作还有变种形式:strncpy,strncath和strnchr。
     ②其它的串操作见C的<string.h>。在不同的高级语言中,对串运算的种类及符号都不尽相同
     ③其余的串操作一般可由这些基本操作组合而成
    【例】求子串的操作可如下实现:
    void substr(char *sub,char *s,int pos,int
    len){
    //s和sub是字符数组,用sub返回串s的第pos个字符起长度为len的子串
    //其中0<=pos<=strlen(s)-1,且数组sub至少可容纳len+1个字符。
    if (pos<0||pos>strlen(s)-1||len<0)
         Error("parameter error!");
    strncpy(sub,&s[pos],len);
    //从s[pos]起复制至多len个字符到sub

    CString 型转化成 int 型

      把 CString 类型的数据转化成整数类型最简单的方法就是使用标准的字符串到整数转换例程。
      虽然通常你怀疑使用 _atoi()函数是一个好的选择,它也很少会是一个正确的选择。如果你准备使用 Unicode  字符,你应该用_ttoi(),它在 ANSI 编码系统中被编译成_atoi(),而在 Unicode编码系统中编译成_wtoi()。你也可以考虑使用_tcstoul()或者_tcstol(),它们都能把字符串转化成任意进制的长整数(如二进制、八进制、十进制或十六进制),不同点在于前者转化后的数据是无符号的(unsigned),而后者相反。看下面的例子
    CString hex = _T("FAB");

    CString decimal = _T("4011");

    ASSERT(_tcstoul(hex, 0, 16) == _ttoi(decimal));

    CString格式化字符串

    与其用 sprintf() 函数或 wsprintf() 函数来格式化一个字符串,还不如用 CString对象的Format()方法:
    CString s;s.Format(_T("The total is %d"), total);  

    用这种方法的好处是你不用担心用来存放格式化后数据的缓冲区是否足够大,这些工作由CString类替你完成。格式化是一种把其它不是字符串类型的数据转化为CString类型的最常用技巧,比如,把一个整数转化成CString类型,可用如下方法:
    CString s;s.Format(_T("%d"), total); 

    在EVC下,我将CString转为Char  *的时候可以这样写

    #include  <atlconv.h>
    ... USES_CONVERSION;
    CString  str="Cstring";
    char  *p;
    p=(char*)W2A((LPCTSTR)str); 

    或者这样写

    CString strDemo;

    char AnsiString[MAX_PATH] = { 0 };
    wcstombs(AnsiString, (LPTSTR)(LPCTSTR)strDemo, strDemo.GetLength());

    或者这样写

    char* = (LPSTR)(LPCTSTR)CString;
    const char* = (LPCSTR)(LPCTSTR)CString;

    或者这样写

    CString strFilePath;
    char FilePath[256];
    memset( FilePath, 0, 256 );
    strFilePath = "hello world";
    WideCharToMultiByte( CP_ACP, 0, strFilePath, -1, FilePath, 256,
    NULL, NULL);
    ...
    或者这样写

    首先获得char缓冲区大小,然后再通过WideCharToMultiByte转换
    CString strConvert;
    char pchBuffer;
    int iSize;
    iSize = WideCharToMultiByte(CP_ACP,0, strFilePath.GetBuffer(0), -1,
    NULL, 0, NULL, NULL);
    pchBuffer = new char[iSize*2 + 1];
    if(pchBuffer != NULL)
    {
          memset(pchBuffer , 0 , (iSize*2 + 1)*sizeof(char));
    }
    WideCharToMultiByte(CP_ACP,0, strFilePath.GetBuffer(0), -1,
    pchBuffer, (iSize*2 + 1), NULL, NULL);

    浅谈EVC中文字符串操作
    EVC在某种意义上说,相当于VC的一个子集。因为大多EVC有的功能,VC也具备,而VC有的功能,EVC则不一定拥有。在VC中,操作字符串很方便,因为WINDOWS 的字处理能力实在是很强大,它支持多种字符集。我们随便使用一个CString str=“你好”,就要以输入我们想要的中文字符串。在EVC中这种情况有所改变,因为WINCE的字处理能力不够强大,它在处理汉字里统一将它示为 UNICODE编码,所以我们在EVC中片理中文字符串时需要用到UNICODE编码。下面结合WINDOWS 下VC字符串的处理,对比一下EVC中文字符串的片理方法。

    一、中文字符串定义
    1、在VC中我们如果定义一个中文字符串,可以使用CString str=“你好”或LPCTSTR  str=“你好”。
    2、在EVC中我们如果想定义一个中文字符串,可以使用如下方法:CString str=_T(“你好”)或者LPCTSTR  str=“你好”,这里LPCTSTR在EVC里就是表示UNICODE字符串。值得注意的是_T()宏中,括号中只能填写常量,不能填定变量。
    二、字符串操作
    1、在VC中我们想拷贝字符串,可以作如下操作:
    char s[20];
    CString str=“你好”;
    strcpy(s,str);
    在EVC中则不能这样做,首先定义中文数组应该用双字节指针wchar_t,而拷贝函数也不能用strcpy,而应该用:wchar_t * wcscpy(wchar_t * wDest,wchar_t wSource);函数,操作如下:
    wchar_t s[20];
    CString str=“你好”;
    wcscpy(s,(LPCTSTR)str); //前面没有转成UNICODE编码,所以这里需要强制转换
    2、在VC中我们想在一个字符串中查找某个子串,只需要作下面的操作:
    CString str=“你是一个好学生”;
    str.Find(“学生”);
    在EVC中不能这样做,因为中文字符串为UNICODE编码,我们必需在查找函数的参数里作如下修改:
    str.Find(_T(“学生”));

    以上是我在用EVC写应用程序时操作中文字符串的一些积累,以文记之,以备不时之需。

    单宽字节互换的程序,估计以后还用得着。

    void MyWideCharToMultiByte(WCHAR* wchars,CHAR* schars,int scharsLen)
    {
        memset(schars,0,scharsLen);
        CString m_snd = wchars;
        int len = m_snd.GetLength();
        CString tmpstr(m_snd); //复制要发送的字符串
        int multibytelen=WideCharToMultiByte( //计算从Unicode转换到Ansi后需要的字节数
            CP_ACP, //根据ANSI code page转换
            WC_COMPOSITECHECK | WC_DEFAULTCHAR, //转换出错用缺省字符代替
            (LPCWSTR)tmpstr.GetBuffer(len), //要转换的字符串地址
            len, //要转换的个数
            0, //转换后字符串放置的地址
            0, //最多转换字符的个数,为0表示返回转换Unicode后需要多少个字节
            0, //缺省的字符:"\0"
            0 //缺省的设置
            );
        WideCharToMultiByte( //转换Unicode到Ansi
            CP_ACP,
            WC_COMPOSITECHECK | WC_DEFAULTCHAR,
            (LPCWSTR)tmpstr.GetBuffer(len),
            len,
            (char *)schars, //转换到缓冲区中
            scharsLen, //最多个字节
            0,
            0
            );
    }
    //程序接收到的字符串最后保存到CString tmpstr中.
    //接收函数片断
    void MyMultiByteToWideChar(char* schars,CString &wstr)
    {
        // TODO: Add your specialized code here and/or call the base class
        //  char * p = "abcdefg我是谁hijk";
        int widecharlen=MultiByteToWideChar( //计算从Ansi转换到Unicode后需要的字节数
            CP_ACP,
            MB_COMPOSITE,
            (char*)schars, //要转换的Ansi字符串
            -1, //自动计算长度
            0,
            0
            );
        CString tmpstr;
        tmpstr.GetBuffer(widecharlen); //为转换后保存Unicode字符串分配内存
        MultiByteToWideChar( //从Ansi转换到Unicode字符
            CP_ACP,
            MB_COMPOSITE,
            (char*)schars,
            -1,
            (LPWSTR)tmpstr.GetBuffer(widecharlen), //转换到tmpstr
            widecharlen //最多转换widecharlen个Unicode字符
            );
        wstr = tmpstr;
    }

    void TestFunction()
    {
        TCHAR abc[]=_T("ab我们的家ab");
        char b[15];
        MyWideCharToMultiByte(abc,b,sizeof(b));
        //  char c[]="ab如果cd就好了!abcdefg";
        CString str;
        MyMultiByteToWideChar(b,str);

        MyWideCharToMultiByte((LPWSTR)str.GetBuffer(0),b,sizeof(b));
    }

     

     

     

     

     

    C++字符串完全指引之一 —— Win32 字符编码

    原著:Michael Dunn
    翻译:Chengjie Sun

    原文出处:CodeProject:The Complete Guide to C++ Strings, Part I
    引言
      毫无疑问,我们都看到过像 TCHAR, std::string, BSTR 等各种各样的字符串类型,还有那些以 _tcs 开头的奇怪的宏。你也许正在盯着显示器发愁。本指引将总结引进各种字符类型的目的,展示一些简单的用法,并告诉您在必要时,如何实现各种字符串类型之间的转换。
      在第一部分,我们将介绍3种字符编码类型。了解各种编码模式的工作方式是很重要的事情。即使你已经知道一个字符串是一个字符数组,你也应该阅读本部分。一旦你了解了这些,你将对各种字符串类型之间的关系有一个清楚地了解。
      在第二部分,我们将单独讲述string类,怎样使用它及实现他们相互之间的转换。
    字符基础 -- ASCII, DBCS, Unicode
      所有的 string 类都是以C-style字符串为基础的。C-style 字符串是字符数组。所以我们先介绍字符类型。这里有3种编码模式对应3种字符类型。第一种编码类型是单子节字符集(single-byte character set or SBCS)。在这种编码模式下,所有的字符都只用一个字节表示。ASCII是SBCS。一个字节表示的0用来标志SBCS字符串的结束。
      第二种编码模式是多字节字符集(multi-byte character set or MBCS)。一个MBCS编码包含一些一个字节长的字符,而另一些字符大于一个字节的长度。用在Windows里的MBCS包含两种字符类型,单字节字符(single-byte characters)和双字节字符(double-byte characters)。由于Windows里使用的多字节字符绝大部分是两个字节长,所以MBCS常被用DBCS代替。
      在DBCS编码模式中,一些特定的值被保留用来表明他们是双字节字符的一部分。例如,在Shift-JIS编码中(一个常用的日文编码模式),0x81-0x9f之间和 0xe0-oxfc之间的值表示"这是一个双字节字符,下一个子节是这个字符的一部分。"这样的值被称作"leading bytes",他们都大于0x7f。跟随在一个leading byte子节后面的字节被称作"trail byte"。在DBCS中,trail byte可以是任意非0值。像SBCS一样,DBCS字符串的结束标志也是一个单字节表示的0。
      第三种编码模式是Unicode。Unicode是一种所有的字符都使用两个字节编码的编码模式。Unicode字符有时也被称作宽字符,因为它比单子节字符宽(使用了更多的存储空间)。注意,Unicode不能被看作MBCS。MBCS的独特之处在于它的字符使用不同长度的字节编码。Unicode字符串使用两个字节表示的0作为它的结束标志。
      单字节字符包含拉丁文字母表,accented characters及ASCII标准和DOS操作系统定义的图形字符。双字节字符被用来表示东亚及中东的语言。Unicode被用在COM及Windows NT操作系统内部。
      你一定已经很熟悉单字节字符。当你使用char时,你处理的是单字节字符。双字节字符也用char类型来进行操作(这是我们将会看到的关于双子节字符的很多奇怪的地方之一)。Unicode字符用wchar_t来表示。Unicode字符和字符串常量用前缀L来表示。例如:

    wchar_t wch = L''1''; // 2 bytes, 0x0031
    wchar_t* wsz = L"Hello"; // 12 bytes, 6 wide characters

    字符在内存中是怎样存储的
      单字节字符串:每个字符占一个字节按顺序依次存储,最后以单字节表示的0结束。例如。"Bob"的存贮形式如下:

    42
    6F
    62
    00

    B
    o
    b
    BOS

    Unicode的存储形式,L"Bob"

    42 00
    6F 00
    62 00
    00 00

    B
    o
    b
    BOS

    使用两个字节表示的0来做结束标志。
      一眼看上去,DBCS 字符串很像 SBCS 字符串,但是我们一会儿将看到 DBCS 字符串的微妙之处,它使得使用字符串操作函数和永字符指针遍历一个字符串时会产生预料之外的结果。字符串" " ("nihongo")在内存中的存储形式如下(LB和TB分别用来表示 leading byte 和 trail byte)

    93 FA
    96 7B
    8C EA
    00

    LB TB
    LB TB
    LB TB
    EOS




    EOS

    值得注意的是,"ni"的值不能被解释成WORD型值0xfa93,而应该看作两个值93和fa以这种顺序被作为"ni"的编码。
    使用字符串处理函数
      我们都已经见过C语言中的字符串函数,strcpy(), sprintf(), atoll()等。这些字符串只应该用来处理单字节字符字符串。标准库也提供了仅适用于Unicode类型字符串的函数,比如wcscpy(), swprintf(), wtol()等。
      微软还在它的CRT(C runtime library)中增加了操作DBCS字符串的版本。Str***()函数都有对应名字的DBCS版本_mbs***()。如果你料到可能会遇到DBCS字符串(如果你的软件会被安装在使用DBCS编码的国家,如中国,日本等,你就可能会),你应该使用_mbs***()函数,因为他们也可以处理SBCS字符串。(一个DBCS字符串也可能含有单字节字符,这就是为什么_mbs***()函数也能处理SBCS字符串的原因)
      让我们来看一个典型的字符串来阐明为什么需要不同版本的字符串处理函数。我们还是使用前面的Unicode字符串 L"Bob":

    42 00
    6F 00
    62 00
    00 00

    B
    o
    b
    BOS

      因为x86CPU是little-endian,值0x0042在内存中的存储形式是42 00。你能看出如果这个字符串被传给strlen()函数会出现什么问题吗?它将先看到第一个字节42,然后是00,而00是字符串结束的标志,于是strlen()将会返回1。如果把"Bob"传给wcslen(),将会得出更坏的结果。wcslen()将会先看到0x6f42,然后是0x0062,然后一直读到你的缓冲区的末尾,直到发现00 00结束标志或者引起了GPF。
      到目前为止,我们已经讨论了str***()和wcs***()的用法及它们之间的区别。Str***()和_mbs**()之间的有区别区别呢?明白他们之间的区别,对于采用正确的方法来遍历DBCS字符串是很重要的。下面,我们将先介绍字符串的遍历,然后回到str***()与_mbs***()之间的区别这个问题上来。
    正确的遍历和索引字符串
      因为我们中大多数人都是用着SBCS字符串成长的,所以我们在遍历字符串时,常常使用指针的++-和-操作。我们也使用数组下标的表示形式来操作字符串中的字符。这两种方式是用于SBCS和Unicode字符串,因为它们中的字符有着相同的宽度,编译器能正确的返回我们需要的字符。
      然而,当碰到DBCS字符串时,我们必须抛弃这些习惯。这里有使用指针遍历DBCS字符串时的两条规则。违背了这两条规则,你的程序就会存在DBCS有关的bugs。

  • 1.在前向遍历时,不要使用++操作,除非你每次都检查lead byte;
  • 2.永远不要使用-操作进行后向遍历。
  •   我们先来阐述规则2,因为找到一个违背它的真实的实例代码是很容易的。假设你有一个程序在你自己的目录里保存了一个设置文件,你把安装目录保存在注册表中。在运行时,你从注册表中读取安装目录,然后合成配置文件名,接着读取该文件。假设,你的安装目录是C:\Program Files\MyCoolApp,那么你合成的文件名应该是C:\Program Files\MyCoolApp\config.bin。当你进行测试时,你发现程序运行正常。
      现在,想象你合成文件名的代码可能是这样的:

    bool GetConfigFileName ( char* pszName, size_t nBuffSize )
    {
        char szConfigFilename[MAX_PATH];
     
        // Read install dir from registry... we''ll assume it succeeds.
     
        // Add on a backslash if it wasn''t present in the registry value.
        // First, get a pointer to the terminating zero.
        char* pLastChar = strchr ( szConfigFilename, ''\0'' );
     
        // Now move it back one character.
        pLastChar--;  
     
        if ( *pLastChar != ''\\'' )
            strcat ( szConfigFilename, "\\" );
     
        // Add on the name of the config file.
        strcat ( szConfigFilename, "config.bin" );
     
        // If the caller''s buffer is big enough, return the filename.
        if ( strlen ( szConfigFilename ) >= nBuffSize )
            return false;
        else
            {
            strcpy ( pszName, szConfigFilename );
            return true;
            }
    }      
      这是一段很健壮的代码,然而在遇到 DBCS 字符时它将会出错。让我们来看看为什么。假设一个日本用户使用了你的程序,把它安装在 C:\。下面是这个名字在内存中的存储形式:

    43
    3A
    5C
    83 88
    83 45
    83 52
    83 5C
    00

    LB TB
    LB TB
    LB TB
    LB TB

    C
    :
    \




    EOS

      当使用 GetConfigFileName() 检查尾部的''\\''时,它寻找安装目录名中最后的非0字节,看它是等于''\\''的,所以没有重新增加一个''\\''。结果是代码返回了错误的文件名。
      哪里出错了呢?看看上面两个被用蓝色高量显示的字节。斜杠''\\''的值是0x5c。'' ''的值是83 5c。上面的代码错误的读取了一个 trail byte,把它当作了一个字符。
      正确的后向遍历方法是使用能够识别DBCS字符的函数,使指针移动正确的字节数。下面是正确的代码。(指针移动的地方用红色标明)

    bool FixedGetConfigFileName ( char* pszName, size_t nBuffSize )
    {
        char szConfigFilename[MAX_PATH];
     
        // Read install dir from registry... we''ll assume it succeeds.
     
        // Add on a backslash if it wasn''t present in the registry value.
        // First, get a pointer to the terminating zero.
        char* pLastChar = _mbschr ( szConfigFilename, ''\0'' );
     
        // Now move it back one double-byte character.
        pLastChar = CharPrev ( szConfigFilename, pLastChar );
     
        if ( *pLastChar != ''\\'' )
            _mbscat ( szConfigFilename, "\\" );
     
        // Add on the name of the config file.
        _mbscat ( szConfigFilename, "config.bin" );
    
         // If the caller''s buffer is big enough, return the filename.
        if ( _mbslen ( szInstallDir ) >= nBuffSize )
            return false;
        else
            {
            _mbscpy ( pszName, szConfigFilename );
            return true;
            }
    }
    
      上面的函数使用CharPrev() API使pLastChar向后移动一个字符,这个字符可能是两个字节长。在这个版本里,if条件正常工作,因为lead byte永远不会等于0x5c。
      让我们来想象一个违背规则1的场合。例如,你可能要检测一个用户输入的文件名是否多次出现了'':''。如果,你使用++操作来遍历字符串,而不是使用CharNext(),你可能会发出不正确的错误警告如果恰巧有一个trail byte它的值的等于'':''的值。
    与规则2相关的关于字符串索引的规则:
    2a. 永远不要使用减法去得到一个字符串的索引。

    违背这条规则的代码和违背规则2的代码很相似。例如,

    char* pLastChar = &szConfigFilename [strlen(szConfigFilename) - 1];

    这和向后移动一个指针是同样的效果。
    回到关于str***()和_mbs***()的区别
      现在,我们应该很清楚为什么_mbs***()函数是必需的。Str***()函数根本不考虑DBCS字符,而_mbs***()考虑。如果,你调用strrchr("C:\\ ", ''\\''),返回结果可能是错误的,然而_mbsrchr()将会认出最后的双字节字符,返回一个指向真的''\\''的指针。
      关于字符串函数的最后一点:str***()和_mbs***()函数认为字符串的长度都是以char来计算的。所以,如果一个字符串包含3个双字节字符,_mbslen()将会返回6。Unicode函数返回的长度是按wchar_t来计算的。例如,wcslen(L"Bob")返回3。
    Win32 API中的MBCS和Unicode
    两组 APIs:
      尽管你也许从来没有注意过,Win32中的每个与字符串相关的API和message都有两个版本。一个版本接受MBCS字符串,另一个接受Unicode字符串。例如,根本没有SetWindowText()这个API,相反,有SetWindowTextA()和SetWindowTextW()。后缀A表明这是MBCS函数,后缀W表示这是Unicode版本的函数。
      当你 build 一个 Windows 程序,你可以选择是用 MBCS 或者 Unicode APIs。如果,你曾经用过VC向导并且没有改过预处理的设置,那表明你用的是MBCS版本。那么,既然没有 SetWindowText() API,我们为什么可以使用它呢?winuser.h头文件包含了一些宏,例如:

    BOOL WINAPI SetWindowTextA ( HWND hWnd, LPCSTR lpString );
    BOOL WINAPI SetWindowTextW ( HWND hWnd, LPCWSTR lpString );
     
    #ifdef UNICODE
    #define SetWindowText  SetWindowTextW
    #else
    #define SetWindowText  SetWindowTextA
    #endif      
    当使用MBCS APIs来build程序时,UNICODE没有被定义,所以预处理器看到:
    #define SetWindowText SetWindowTextA

      这个宏定义把所有对SetWindowText的调用都转换成真正的API函数SetWindowTextA。(当然,你可以直接调用SetWindowTextA() 或者 SetWindowTextW(),虽然你不必那么做。)
      所以,如果你想把默认使用的API函数变成Unicode版的,你可以在预处理器设置中,把_MBCS从预定义的宏列表中删除,然后添加UNICODE和_UNICODE。(你需要两个都定义,因为不同的头文件可能使用不同的宏。) 然而,如果你用char来定义你的字符串,你将会陷入一个尴尬的境地。考虑下面的代码:

    HWND hwnd = GetSomeWindowHandle();
    char szNewText[] = "we love Bob!";
    SetWindowText ( hwnd, szNewText );

    在预处理器把SetWindowText用SetWindowTextW来替换后,代码变成:

    HWND hwnd = GetSomeWindowHandle();
    char szNewText[] = "we love Bob!";
    SetWindowTextW ( hwnd, szNewText );

      看到问题了吗?我们把单字节字符串传给了一个以Unicode字符串做参数的函数。解决这个问题的第一个方案是使用 #ifdef 来包含字符串变量的定义:

    HWND hwnd = GetSomeWindowHandle();
    #ifdef UNICODE
    wchar_t szNewText[] = L"we love Bob!";
    #else
    char szNewText[] = "we love Bob!";
    #endif
    SetWindowText ( hwnd, szNewText );

    你可能已经感受到了这样做将会使你多么的头疼。完美的解决方案是使用TCHAR.
    使用TCHAR
      TCHAR是一种字符串类型,它让你在以MBCS和UNNICODE来build程序时可以使用同样的代码,不需要使用繁琐的宏定义来包含你的代码。TCHAR的定义如下:

    #ifdef UNICODE
    typedef wchar_t TCHAR;
    #else
    typedef char TCHAR;
    #endif

    所以用MBCS来build时,TCHAR是char,使用UNICODE时,TCHAR是wchar_t。还有一个宏来处理定义Unicode字符串常量时所需的L前缀。

    #ifdef UNICODE
    #define _T(x) L##x
    #else
    #define _T(x) x
    #endif

      ##是一个预处理操作符,它可以把两个参数连在一起。如果你的代码中需要字符串常量,在它前面加上_T宏。如果你使用Unicode来build,它会在字符串常量前加上L前缀。

    TCHAR szNewText[] = _T("we love Bob!");

      像是用宏来隐藏SetWindowTextA/W的细节一样,还有很多可以供你使用的宏来实现str***()和_mbs***()等字符串函数。例如,你可以使用_tcsrchr宏来替换strrchr()、_mbsrchr()和wcsrchr()。_tcsrchr根据你预定义的宏是_MBCS还是UNICODE来扩展成正确的函数,就像SetWindowText所作的一样。
      不仅str***()函数有TCHAR宏。其他的函数如, _stprintf(代替sprinft()和swprintf()),_tfopen(代替fopen()和_wfopen())。 MSDN中"Generic-Text Routine Mappings."标题下有完整的宏列表。
    字符串和TCHAR typedefs
      由于Win32 API文档的函数列表使用函数的常用名字(例如,"SetWindowText"),所有的字符串都是用TCHAR来定义的。(除了XP中引入的只适用于Unicode的API)。下面列出一些常用的typedefs,你可以在msdn中看到他们。

    type
    Meaning in MBCS builds
    Meaning in Unicode builds

    WCHAR
    wchar_t
    wchar_t

    LPSTR
    zero-terminated string of char (char*)
    zero-terminated string of char (char*)

    LPCSTR
    constant zero-terminated string of char (const char*)
    constant zero-terminated string of char (const char*)

    LPWSTR
    zero-terminated Unicode string (wchar_t*)
    zero-terminated Unicode string (wchar_t*)

    LPCWSTR
    constant zero-terminated Unicode string (const wchar_t*)
    constant zero-terminated Unicode string (const wchar_t*)

    TCHAR
    char
    wchar_t

    LPTSTR
    zero-terminated string of TCHAR (TCHAR*)
    zero-terminated string of TCHAR (TCHAR*)

    LPCTSTR
    constant zero-terminated string of TCHAR (const TCHAR*)
    constant zero-terminated string of TCHAR (const TCHAR*)

    何时使用 TCHAR 和 Unicode
      到现在,你可能会问,我们为什么要使用Unicode。我已经用了很多年的char。下列3种情况下,使用Unicode将会使你受益:

  • 1.你的程序只运行在Windows NT系统中。
  • 2. 你的程序需要处理超过MAX_PATH个字符长的文件名。
  • 3. 你的程序需要使用XP中引入的只有Unicode版本的API.
  •   Windows 9x 中大多数的 API 没有实现 Unicode 版本。所以,如果你的程序要在windows 9x中运行,你必须使用MBCS APIs。然而,由于NT系统内部都使用Unicode,所以使用Unicode APIs将会加快你的程序的运行速度。每次,你传递一个字符串调用MBCS API,操作系统会把这个字符串转换成Unicode字符串,然后调用对应的Unicode API。如果一个字符串被返回,操作系统还要把它转变回去。尽管这个转换过程被高度优化了,但它对速度造成的损失是无法避免的。
      只要你使用Unicode API,NT系统允许使用非常长的文件名(突破了MAX_PATH的限制,MAX_PATH=260)。使用Unicode API的另一个优点是你的程序会自动处理用户输入的各种语言。所以一个用户可以输入英文,中文或者日文,而你不需要额外编写代码去处理它们。
      最后,随着windows 9x产品的淡出,微软似乎正在抛弃MBCS APIs。例如,包含两个字符串参数的SetWindowTheme() API只有Unicode版本的。使用Unicode来build你的程序将会简化字符串的处理,你不必在MBCS和Unicdoe之间相互转换。
      即使你现在不使用Unicode来build你的程序,你也应该使用TCHAR及其相关的宏。这样做不仅可以的代码可以很好地处理DBCS,而且如果将来你想用Unicode来build你的程序,你只需要改变一下预处理器中的设置就可以实现了。

    作者简介
      Michael Dunn:居住在阳光城市洛杉矶。他是如此的喜欢这里的天气以致于想一生都住在这里。他在4年级时开始编程,那时用的电脑是Apple //e。1995年,在 UCLA 获得数学学士学位,随后在Symantec 公司做 QA 工程师,在 Norton AntiVirus 组工作。他自学了 Windows 和 MFC 编程。1999-2000年,他设计并实现了 Norton AntiVirus 的新界面。 
      Michael 现在在 Napster(一个提供在线订阅音乐服务的公司)做开发工作,他还开发了UltraBar,一个IE工具栏插件,它可以使网络搜索更加容易,给了 googlebar 以沉重打击;他还开发了 CodeProject SearchBar;与人共同创建了 Zabersoft 公司,该公司在洛杉矶和丹麦的 Odense 都设有办事处。
      他喜欢玩游戏。爱玩的游戏有 pinball, bike riding,偶尔还玩 PS, Dreamcasth 和 MAME 游戏。他因忘了自己曾经学过的语言:法语、汉语、日语而感到悲哀。

    May 15

    美丽的调兵山---国家级园林城市

     
    May 03

    收集一些.NET开发资源站点和部分优秀.NET开源项目 -转载

    4fe75cd5471a

    Net General

    Asp.Net

    Visual Studio

    Visual C#.Net

    VB.NET

    .NET社区

    .NET博客

    Ajax

    工具下载

    开源程序

    .NET开源项目

    SharpDevelop
    强大的插件系统,通过Addin构建成一个功能齐全的.net开发IDE。核心是AddInTree。跟随这个项目开发许多有用的组件,比如功能文本编辑器(ICSharpCode.TextEditor),SharpZipLib等。
    链接:http://www.icsharpcode.net/
    DotNetNuke
    这个就是著名DNN,使用VB.NET进行开发。通过其基本架构可进行堆积木式快速建站。而且支持子网站系统。其由asp.net Portal start kit进化而来。
    链接:http://www.dnnchina.net/http://www.dotnetnuke.com
    Community Server
    这个也是一个很著名的ASP.NET项目,记得好像最早系统原形为asp.net Forums,后来加入了.Text Blog 和nGallery成为一个完整的通用系统。对应的中文版本为宝玉修改的CCS。
    链接:http://communityserver.org/
    Rainbow
    另外一个类似于DNN的系统,使用C#进行开发。
    链接:http://www.rainbowportal.net/
    RssBandit
    一个客户端的RSS查看器,使用C# 进行开发,最大的特点是数据存储采用xml文件。
    链接:http://www.rssbandit.org/
    FreeTextbox
    Web上的一个Html超文本编辑器,早些版本是开源的,现在还是免费使用,不过源代码需要购买。
    链接:http://www.freetextbox.com
    World Wind
    使用.NET开发的一个Windows窗体系统,以地球外观看得角度提供全球定位功能,类似于Google Earth。
    链接:http://worldwind.arc.nasa.gov
    log4net
    对应Java中的log4j。一个强大的日志管理模块。
    链接:http://logging.apache.org/log4net/
    Monodevelop
    非Windows 系统下的.net 平台开发工具。
    链接:http://www.monodevelop.com
    Paint.NET
    使用.net开发的画图软件,功能不错。
    链接:http://www.getpaint.net/index.html
    Nunit
    对应Java中的Junit,非常著名的单元测试工具。
    链接:http://www.nunit.org/
    FCKeditor
    Web上的又一个Html超文本编辑器。
    链接:http://www.fckeditor.net/
    Nlog
    一个日志管理库,类似于Log4Net。
    链接:http://www.nlog-project.org/
    ManagedSpy
    .net 平台下的Spy ++,支持通过.net 2.0开的Windows Forms应用程序。
    链接:http://msdn.microsoft.com/msdnmag/issues/06/04/ManagedSpy/
    Guidance Explore
    类似于一个.net平台编程问题简答的FAQ。不过提供的都是英文。
    链接:http://www.codeplex.com/Wiki/View.aspx?ProjectName=guidanceExplorer
    Terrarium
    一个.net开发的多人游戏。玩这个游戏可以提高编程能力。
    链接:http://www.windowsforms.net/Default.aspx?tabindex=4&tabid=49
    TaskVision
    任务管理系统,一个经典的Smart Client智能客户端程序。
    链接:http://www.windowsforms.net/Default.aspx?tabindex=4&tabid=49
    IssueVision
    事务管理系统,Smart Client智能客户端程序。
    链接:http://www.windowsforms.net/Default.aspx?tabindex=4&tabid=49
    FotoVision
    又一个值得学习的.net开发的Windows应用程序。
    链接:http://www.windowsforms.net/Default.aspx?tabindex=4&tabid=49
    Infragistics Tracker Application
    由Infragistics开发的Smart Client智能客户端程序。
    链接:http://www.windowsforms.net/Default.aspx?tabindex=4&tabid=49
    Windows Forms RSS Portal
    一个.net 开发的聚合器。
    链接:http://www.windowsforms.net/Default.aspx?tabindex=4&tabid=49
    Enterprise Library
    微软的企业库,对原早些时候开发的一些Block 模块进行整合提供企业统一的接口,新版本使用了.net 2.0的的许多功能。
    链接:http://msdn.microsoft.com/practices/
    PetShop
    基于N-tier设计的电子商务网站,没什么好说的了。
    链接:http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnbda/html/bdasamppet4.asp
    XmlNotepad
    一个用.net 开发的xml文件编辑器。
    链接:http://www.microsoft.com/china/msdn/library/data/xml/xmlnotepad.mspx
    DockManager Control
    一个很不错的实现类似于VS 2005的界面某些功能的组件。
    链接:http://www.codeproject.com/vb/net/DockPanelSkin.asp
    Starter Kits for Visual Web Developer
    该套件为学习研究应用asp.net2.0的开发人员提供许多宝贵资源,很不错。
    链接:http://www.asp.net/downloads/starterkits/default.aspx?tabid=62

    Excel 2007 连接 SQL SERVER 获取数据

    方法一:使用excel中获取外部数据向导

    1.创建到SQL SERVER的连接
    image 

    2.输入服务器名称,用户名,密码
    image

    3.选择需要连接的数据库
    image
    image
    image 
    image
    image
    image 

    方法二:利用ADO的Connection对象来连接数据库

    image
    image
    image
    image
    image
    image 
    image

    April 29

    windows7 登陆不用输入密码的方法

    方法1:可以在域安全策略设置。
    方法2:用管理员登陆后运行control userpassword2,选择不用密码登录,按应用,选择用来登陆的默认的域账号和输入正确的密码。

    image
    image

    April 12

    信息化的定义

    现在各种信息化定义,林林总总,但还没有一个让人完全信服的。不识庐山真面目,原因往往在于“身在此山中”。
    我们今天给信息化下定义的难处在对现代化的理解上。最明显的一点就是,现在所有的信息化定义,几乎都在躲闪一个问题—信息化与工业化到底是一次现代化还是两次现代化?不对这个根本的问题进行回答,我们的任何信息化定义可能无法经得住时间的考验。当然,不是说不能用各种临时性的定义来解决阶段性的问题,但把握阶段性与把握实质是并不矛盾的两件事。
    两次现代化有质的区别
    所谓一次现代化与两次现代化,说的是现代化有没有质的不同与质的飞跃。在这个问题上,人们的认识是混乱的。我认为,工业化是第一次现代化,信息化是第二次现代化,二者有内在联系,也有本质区别。我主张要在战略上搞明白,哪怕搞明白了目前没条件做,也可以分解为阶段性的策略。
    我们先从经验上看,工业化与信息化是否有质的不同。比如,工业化组织的金字塔结构与信息化组织的扁平化;工业化网络的集中性特征与信息化网络的分布性特征,这明明是特点相反,怎么能说没有质的不同呢?许多坚持认为信息化在本质上与工业化没有什么不同的人对此视而不见,根本的认识分歧其实不是出在现象认知上,而是出在范式认知上;不是出在体系的保护带上,而是出在体系的内核上。
    中国虽然较早提出信息化这个词,走在了世界前列,但中国与世界各国有一个非常不同的氛围—在主流学者中,忌讳甚至痛恨谈范式的转变。你可以说信息化春风拂面,哪个角落都能扫到,但你要说从根上触及传统引起质变,有人非跟你急不可。
    我们现在对信息化总结得很高,但高并不等于范式。打个比方,清王朝也高度重视工业技术应用,把船坚炮利视为关乎大清帝国的生死之道。到最后,京城都让人连锅端了,不能也不敢说他们不重视工业化。但问题是,船坚炮利并非工业化,而只不过是工业化之“用”,或者说“技术应用”。清王朝到死也没有把工业化在范式这个层面定义清楚。反过来说,什么样的反思,属于对范式的反思呢?同样举个例子:前现代性、现代性、后现代性这种界定,就是指向范式的定义方法。
    我们定义信息化,要搞清楚,它与工业化有什么区别和联系,工业化的进步性在哪里,局限性在哪里。我们现在定义的要害在于只是从技术特征上总结,如六要素的总结,资源特征、产业特征等等。只要把这些要素中的定语“信息”换成“工业”,就可以变成工业化的“定义”。你能说工业化就是工业资源、工业技术应用,工业产业等等吗?不能。因为远没有抓住实质。工业化中的专业化分工、科层制结构,人的异化等等实质内涵,在这样的定义里没有任何痕迹。这就是我说的定义中的“逃避”问题。
    反观后现代性对现代性的反思,就要深刻得多。后现代主义认为,工业化,或者说现代性,其体系内核是以二元论为基础的普遍主义。我们在定义信息化时,既不敢对工业化的局限性挖掘更深的根子,也不肯对信息化的根据进行更进一步探究。一方面说要跳出技术观点看信息化,另一方面真跳出了技术观点,深入到人文道理,又多少有些不肯。
    信息化以生命化为导向
    在细致地比较了十多年来信息化的种种定义后,信息化外围的特征被概括了个遍,但缺乏灵魂。而且所有这些外在特征,差不多又都是那些可以用工业化的体系内核吸收的东西。而那些信息化特殊的东西,在这样的定义中,又显得有些神龙见首不见尾。
    如果以定义的传神而非严谨为标准,我认为信息化可以说是以生命化为导向的现代化,它是对以机械化为导向的现代化(即工业化)的扬弃。我很欣赏军队信息化中,将信息化与机械化作为一个对子的做法。当然,这里的机械化,可以扩展为广义的机械化来理解。
    机械化,不光是指机械化技术、产业、设施,而且是社会的机械化、精神与文化的机械化。举例来说,笛卡尔理性主义就是典型的机械化。工业化强调工具理性,把什么都当成工具看待。与机械化相反的是生命化,信息技术革命与生物技术革命都是生命化运动,都是给世界重新赋予灵性的运动。网络通讯是提供灵性的神经系统,计算机和DNA是在为灵性提供基础材料的编码解码。
    如果站在文明跃升的高度看工业化和信息化,现代性所强调的祛魅与后现代性所强调的返魅范式,恰恰接触到了问题的实质。如果我们把“魅”理解为生命性的话,启蒙运动提倡的祛魅是指将人从自然生命中解放出来,进入到技术机械化与社会机械化的更高状态,这是工业化的灵魂;而后现代提倡的返魅在于针对机械化过度带来的弊端,主张从机械化复归到更高阶段的生命化,这正是信息化的灵魂所在。信息化在生命化意义上的返魅,也不是返回第一次浪潮那种自然生命,而是第三次浪潮的复杂生命,即社会化系统的生命化。
    我们不妨用实践“验算”一下,信息化是不是生命化。电子业务(包括电子商务和电子政务)到底要达到什么目标状态?电子业务最终通向的是使社会从机械体变为有机体。有机体或者说生命体,表现为对环境反映灵敏,善于面对信息不确定性,有较强的创新与演化能力。通过信息化,商务和政务的最大改变,应该是让组织像具有灵性的生命体一样,体贴人、关怀人,非常灵敏地跟着目标人群变。这才是以人为本。所有信息化要素只是跳板,如信息资源是活化剂,网络设施是血管等;扁平化和分布式计算,都不过是在仿生等等。这样才能跳出信息技术和生命技术的浅层含义,用世界观的语言来说话。
    我个人提出一个“科学”的判据,用来区分机械化与信息化:所有生命体的效能曲线,都遵循边际成本递减;所有机械体的效能曲线,都遵循边际成本递增。在基本范式上确有区别:它们的收益与成本之比的变化率不同,切线斜率的方向相反。这就是两次现代化在实处最不同的地方。
    有生命化的意识与没有,在政策主张上,就可以看出不同。比如,在企业问题上,我主张要提做大、做强、做活,并且把做活放在做大做强之上。出发点和落脚点就是生命化。我认为在信息化的国际环境下,企业只做大做强而不做活,无异于变成恐龙去找死。企业信息化的本质,就是帮助企业做活,提高企业的灵敏度和再生力。
    当然,退一步说,如果我们实在不能从根本上理解什么是信息化,采用实用主义的态度,比错误地定义还是要好一些。因为实用主义至少还有一个好处,是实事求是。

    April 05

    中国考试种类及官方网站

    全国计算机等级考试

    考试网站
    中国教育考试网 中国教育考试网:www.neea.edu.cn
    华夏大地教育网 华夏大地教育网www.edu-edu.com.cn
    中国教育在线 中国教育在线:www.eol.cn

    March 15

    80 年代以来的操作系统 GUI 设计进化史(转)

    投递人 itnews 发布于 2009-03-14 20:15 http://news.cnblogs.com/n/45298/

    70年代,施乐公司 Xerox Palo Alto Research Center (PARC) 的研究人员开发了第一个 GUI 图形用户界面,开启了计算机图形界面的新纪元,80年代以来,操作系统的界面设计经历了众多变迁,OS/2,Macintosh, Windows, Linux, Symbian OS ,各种操作系统将 GUI设计带进新的时代。本文介绍了80年代以来各种操作系统 GUI 界面设计的进化史。

    第一个使用现代图形界面的个人电脑是 Xerox Alto,设计于1973年,该系统并未商用,主要用于研究和大学。
    Source: toastytech.com

    1981-1985
    Xerox 8010 Star (1981年推出)
    这是第一台全集成桌面电脑,包含应用程序和图形用户界面(GUI),一开始叫 The Xerox Star,后改名为 ViewPoint, 最后又改名为 GlobalView。

    Xerox 8010 Star, Source: toastytech.com
    Apple Lisa Office System 1 (1983)
    又称 Lisa OS,这里的 OS 是 Office System的缩写,苹果开发这款机器的初衷是作为文档处理工作站。不幸的是,这款机器的寿命并不长,很快被更便宜的 Macintosh 操作系统取代。LisaOS 几个升级包括 1983年的 Lisa OS2, 1984年的 Lisa OS 7/7 3.1。

    Apple Lisa OS 1, Source: GUIdebook

    Apple Lisa OS 1, Source: GUIdebook
    VisiCorp Visi On (1984)
    Visi On 是为 IBM PC 开发的第一款桌面 GUI,该系统面向大型企业,价格昂贵,使用基于鼠标的 GUI,它内置安装程序与帮助系统,但尚未使用图标。

    VisiCoprt Visi On, Source: toastytech.com

    VisiCoprt Visi On, Source: toastytech.com
    Mac OS System 1.0 (1984)
    System 1.0 是最早的 Mac 操作系统 GUI,已经拥有现代操作系统的几项特点,基于窗体, 使用图标。窗体可以用鼠标拖动,文件与文件夹可以通过拖放进行拷贝。

    Apple Mac System 1.0, Source: toastytech.com
    Amiga Workbench 1.0 (1985)
    一经发布,Amiga 就领先时代。它的 GUI 包含诸如彩色图形(四色:黑,白,蓝,橙),初级多任务,立体声以及多状态图标(选中状态和未选中状态)

    Amiga Workbench 1.0, Source: GUIdebook

    Amiga Workbench 1.0, Source: GUIdebook
    Windows 1.0x (1985)
    1985年,微软终于在图形用户界面大潮中占据了一席之地,Windows 1.0 是其第一款基于 GUI 的操作系统 。使用了 32x32 像素的图标以及彩色图形,其最有趣的功能是模拟时钟动画图标。

    Microsoft Windows 1.01, Source: makowski-berlin.de

    Microsoft Windows 1.01, Source: makowski-berlin.de
    1986 - 1990 IRIX 3 (released in 1986, first release 1984)
    64为 IRIX 操作系统是为 Unix 设计的,它的一个有趣功能是支持矢量图标,这个功能远在 Max OS X 面世前就出现了。

    Silicon Graphics IRIX 3.0, Source: osnews.com
    Windows 2.0x (1987)
    这个版本的 Windows 操作系统中对 Windows 的管理有了很大改进,Windows 可以交叠,改变大小,最大化或最小化。

    Microsoft Windows 2.03, Source: guidebookgallery.org

    Microsoft Windows 2.03, Source: guidebookgallery.org
    OS/2 1.x (released in 1988)
    OS/2 最早由 IBM 和微软合作开发,然而1991年,随着微软将这些技术放到自己的 Windows 操作系统,两家公司决裂,IBM继续开发 OS/2,OS/2 使用的 GUI 被称为 “Presentation Manager (展示管理)”,这个版本的 GUI只支持单色,以及固定图标。

    Microsoft-IBM OS/2 1.1, Source: pages.prodigy.net

    Microsoft-IBM OS/2 1.1, Source: pages.prodigy.net
    NeXTSTEP / OPENSTEP 1.0 (1989)
    Steve Jobs 心血来潮,想为大学和研究机构设计一款完美的电脑,他的这个设想后来造就了一家叫做 NeXT Computer 的公司。
    第一台 NeXT 计算机于1988年发布,不过到了1989年随着 NeXTSTEP 1.0 GUI 的发布才取得显著进展,该 GUI 后来演变成 OPENSTEP。
    该 GUI 的图标很大,48x48像素,包含更多颜色,一开始是单色的,从1.0开始支持彩色,下图中已经可以看到现代 GUI 的影子。

    NeXTSTEP 1.0, Source: kernelthread.com
    OS/2 1.20 (1989)
    OS/2 的下一个小版本在很多方面都做了改进,图标看上去更好看,窗体也显得更平滑。

    OS/2 1.2, Source pages.prodigy.net
    Windows 3.0 (1990)
    到 Windows 3.0, 微软真正认识到 GUI的威力,并对之进行大幅度改进。该操作系统已经支持标准或386增强模式,在增强模式中,可以使用640K以上的扩展内存,让更高的屏幕分辨率和更好的图形成为可能,比如可以支持 SVGA 800x600 或 1024x768。
    同时,微软聘请 Susan Kare 设计 Windows 3.0 的图标,为 GUI 注入统一的风格。

    Microsoft Windows 3.0, Source: toastytech.com

    Microsoft Windows 3.0, Source: toastytech.com
    1991 - 1995 Amiga Workbench 2.04 (1991)
    该版 GUI 包含很多改进,桌面可以垂直分割成不同分辨率和颜色深度,在现在看来似乎有些奇怪。默认的分辨率是 640x256,不过硬件支持更高的分辨率。

    Commodore Amiga Workbench 2.04, Source: guidebookgallery.org
    Mac OS System 7 (released in 1991)
    Mac OS 7 是第一款支持彩色的 GUI,图标中加入了微妙的灰,蓝,黄阴影。

    Apple Mac OS System 7.0, Source: guidebookgallery.org

    Apple Mac OS System 7.0, Source: guidebookgallery.org

    Windows 3.1 (1992)
    该版本的 Windows 支持预装的 TrueType 字体,第一次使 Windows 成为可以用于印刷的系统。Windows 3.0 中,只能通过 Adobe 字体管理器(ATM)实现该功能。该版本同时包含一个叫做 Hotdog Stand 的配色主题。
    配色主题可以帮助某些色盲患者更容易看清图形。
    windows_311_workspace
    Source: Wikipedia
    OS/2 2.0 (1992)
    这是第一个获得世界认可并通过可用性与可访问性测试的 GUI,整个 GUI 基于面向对象模式,每个文件和文件夹都是一个对象,可以同别的文件,文件夹与应用程序关联。它同时支持拖放式操作以及模板功能。
    Os 2 2
    IBM OS/2 2.0, Source: toastytech.com
    Os 2 2
    IBM OS/2 2.0, Source: toastytech.com
    Windows 95 (1995)
    Windows 3.x 之后,微软对整个用户界面进行了重新设计,这是第一个在窗口上加上关闭按钮的 Windows 版本。图标被赋予了各种状态(有效,无效,被选中等),那个著名的“开始”按钮也是第一次出现。对操作系统和 GUI 而言,这是微软的一次巨大飞跃。
    Windows 95
    Microsoft Windows 95, Source: guidebookgallery.org
    Windows 95
    Microsoft Windows 95, Source: guidebookgallery.org
    1996 - 2000 OS/2 Warp 4 (1996)
    IBM 终于争气地推出了 OS/2 Warp 4。桌面上可以放置图标,也可以自己创建文件和文件夹,并推出一个类似 Windows 回收站和 Mac 垃圾箱的文件销毁器,不过一旦放进去进不能再恢复。
    Os 2 Warp 4
    IBM OS/2 Warp 4, Source: toastytech.com
    Os 2 Warp 4
    IBM OS/2 Warp 4, Source: toastytech.com
    Mac OS System 8 (1997)
    该版本的 GUI 支持默认的256色图标,Mac OS 8 最早采用了伪3D图标,其灰蓝色彩主题后来成为 Mac OS GUI 的标志。
    Macos 8
    Apple Mac OS 8, Source: guidebookgallery.org
    Windows 98 (1998)
    图标风格和 Windows 95 几无二致,不过整个 GUI 可以使用超过256色进行渲染,Windows 资源管理器改变巨大,第一次出现活动桌面。
    Windows 98
    Microsoft Windows 98, Source: toastytech.com
    KDE 1.0 (1998)
    KDE是 Linux 的一个统一图形用户界面环境。
    Kde 1
    KDE 1.0, Source: ditesh.gathani.org
    GNOME 1.0 (1999)
    GNOME 桌面主要为 Red Hat Linux 开发,后来也被别的 Linux 采用。
    Gnome 1
    Red Hat Linux GNOME 1.0.39, Source: visionfutur.com
    2001 - 2005 Mac OS X (released in 2001)
    2000年初,苹果宣布推出其 Aqua 界面,2001年,推出全新的操作系统 Mac OS X。默认的 32x32, 48x48 被更大的 128x128 平滑半透明图标代替。
    该 GUI 一经推出立即招致大量批评,似乎用户都如此大的变化还不习惯,不过没过多久,他们呢就接受了这种新风格,如今这种风格已经成了 Mac OS 的招牌。
    Mac osx 1
    Apple Mac OS X 10.1 Source: guidebookgallery.org
    Windows XP (released in 2001)
    每一次微软推出重要的操作系统版本,其 GUI 也必定有巨大的改变,Windows XP 也不例外,这个 GUI 支持皮肤,用户可以改变整个 GUI 的外观与风格,默认图标为 48x48,支持上百万颜色。
    Windows xp
    Microsoft Windows XP Professional, Source: guidebookgallery.org
    KDE 3 (released in 2002)
    自1.0版发布以来,KDE 有了长足的改进,对所有图形和图标进行了改进并统一了用户体验。
    Kde 3
    KDE 3.0.1, Source: netbsd.org
    2007 - 2009 (current)
    Windows Vista (released in 2007)
    这是微软向其竞争对手做出的一个挑战,Vista 中同样包含很多 3D 和动画,自 Windows 98 以来,微软一直尝试改进桌面,在 Vista 中,他们使用类似饰件的机制替换了活动桌面。
    Windows Vista
    Microsoft Windows Vista, Source: technology.berkeley.edu
    Mac OS X Leopard (released in 2007)
    对于第六代 Max OS X,苹果又一次对用户界面做出改进。基本的 GUI 仍是 Aqua,但看上去更 3D 一些,也包含了 3D 停靠坞以及很多动画与交互功能。
    Mac osx Leopard
    Apple Mac OS X 10.5 Leopard, Source: skattertech.com
    KDE (v4.0 Jan. 2009, v4.2 Mar. 2009)
    KDE 4 的 GUI 提供了很多新改观,如动画的,平滑的,有效的窗体管理,图标尺寸可以很容易调整,几乎任何设计元素都可以轻松配置。相对前面的版本绝对是一个巨大的改进。
    kde
    Source: Wikipedia
    鸣谢

    http://www.guidebookgallery.org/
    http://toastytech.com/guis/index.html

    Windows 7 可能在夏末提前发布
    image

    微软产品路线图

    Windows操作系统进化图

    January 10

    Windows7初体验

    1.令我最感欣慰的是驱动程序全部自动安装.
    image

    2.可以激活使用,这应该是微软发布的最成熟的beta版了,可以很方便的使
    image

    3.许多操作非常方便,特别是任务栏,用着很舒服。

    December 20

    信息记录

    联想黑机器
    T开天A4000 P4 2.5G 25680DVDSN(XP)(10305)主机编号:NA04967716

    December 09

    codeplex上两个新.net工程值得关注

    第一个:http://www.codeplex.com/oxite

    微软正在CodePlex网站开发一个CMS系统,它是开源的,目前正处于Alpha阶段,开发代号“Oxite”。12月5日,微软将源代码正式公布出来,采用Microsoft Public License (MS-Pl)授权,微软对它的定位是一个超过博客引擎并可以支持大网站运作的CMS系统,因为它采用SQL Server驱动并内置Live Search的搜索技术,并且可以全面利用ASP.NET MVC的特性,开发软件也非常多样。微软之前曾有过一个SharePoint Server作为门户解决方案,而Oxite更像是一个稍轻量级的开源产品。

    第二个:http://www.codeplex.com/cracknetproject
    image 

    回想上个世纪90年代,应用开发者经常通过COM Automation来暴露其API。这使得第三方开发者可以通过大量扩展点来附加并操纵运行着的应用。不幸的是,在.NET时代这种交互的能力已经江河日下了。Crack.NET试图通过基于WinForm和WPF的.NET应用来重新获得这种能力。通过丰富的GUI(比Visual Studio的属性检测器强多了),用户可以附加到大多数.NET应用。这在很大程度上依赖于.NET基础设施,因此之前的应用开发者无需提供任何显式的回调。一旦附加上,用户就可以随意探测并操纵运行着的应用了。然而真正的乐趣却来自于脚本。通过使用IronPython脚本,开发者可以将代码注入到运行着的应用中以增加他们想要的任何特性。随着.NET和DLR的日渐流行,我们可以预计未来将有很多人从事应用(这些应用可能并不想被扩展)插件的编写工作。