随笔-6  评论-0  文章-0  trackbacks-0
  2016年2月15日
对于一个扎根于Windows的开发者来说,很难离开图形界面,如直接使用无图形界面的Linux(以下使用的是CentOS)进行编码,会严重影响该开发者的工作效率。本文描述了如何在Windows下面搭建Linux开发平台,以用于Linux服务器开发。这里使用的工具是Source insight、Virtualbox、Samba、XShell,其中Source insight用来编辑代码(代码是放在CentOS下面的),Virtualbox用来安装CentOS虚拟机,这里使用的是没有图形界面的CentOS7,Samba用来共享Windows与Linux的目录,XShell用来远程登录CentOS
虚拟机,这个工具比原始的Linux终端好用,提供了诸多类似于Windows图形界面支持的操作,如选择、复制和粘贴等。
从前面的描述可以看到,我们只是在Windows下面编写代码,而构建与调试,都是在CentOS下面完成的,本文不涉及在Windows下面构建与调试Linux程序。
安装Source insight、Virtualbox、XShell是非常简单的。
安装与配置CentOS虚拟机。
1、安装CentOS。这里需要注意的是,CentOS默认安装的是最小安装,最小安装里面只包含少量的工具,没有gcc,gdb等常用的开发工具,因此要选择合适自己的安装方式,最好把要使用的工具都装上。
2、配置网络。因为我们在开发的时候要将CentOS的目录共享到Windows,所以我们要保证两边都能够通信,所以这里我们选择使用桥接网络,然后根据具体情况进行CentOS的网络配置。
3、安装Samba。Samba安装在CentOS中,用以共享CentOS的目录。
4、映射共享目录。Source insight使用网络路径时,会出现一些莫名其妙的错误,因此我们最后将CentOS的共享目录映射为一个驱动器,如B盘。
安装XShell。XShell提供了丰富的界面交互功能,可以根据自己的爱好选择不同的主题元素,如字体、背景等。
既然使用了XShell,那么Virtualbox的终端界面就可以不要了,我们可以使用Virtualbox提供的管理工具将CentOS隐藏到后台运行。
posted @ 2016-02-15 11:53 weigtcs 阅读(258) | 评论 (0)编辑 收藏
  2015年7月29日
很多时候想使用字符串格式化输出,但是std::wstring偏偏没有提供这个方法。CString只存在于ATL/MFC,使用Win32平台没有CString可用,使用底层的spintf之类的函数,又时常担心buffer越界,写重复的越界检测之类的代码...所以这里把CString的Format方法搬了过来:
String.h
1 class String : public std::wstring
2 {
3 public:
4     void Format(const wchar_t* pszFormat, );
5 protected:
6     void FormatV(const wchar_t* pszFormat, va_list args);
7     int GetFormattedLength(const wchar_t* pszFormat, va_list args);
8     int Format(wchar_t* pszBuffer, ULONG nLength, const wchar_t* pszFormat, va_list args);
9 };
String.cpp
std::wstring StrFormat( const wchar_t* pstrFormat,  )
{
    WCHAR szBuffer[300] = { 0 };
    va_list args;
    va_start(args, pstrFormat);
    ::wvnsprintf(szBuffer, lengthof(szBuffer) - 2, pstrFormat, args);
    wcscat_s(szBuffer, 300, L"\n");
    va_end(args);
    return szBuffer;
}

void String::Format( const wchar_t* pszFormat,  )
{
    va_list arglist;
    va_start(arglist, pszFormat);
    FormatV(pszFormat, arglist);
    va_end(arglist);
}

int String::Format( wchar_t* pszBuffer, ULONG nLength, const wchar_t* pszFormat, va_list args )
{
    return vswprintf_s(pszBuffer, nLength, pszFormat, args);
}

void String::FormatV( const wchar_t* pszFormat, va_list args )
{
    if (pszFormat == NULL)
    {
        return;
    }
    ULONG nLength = GetFormattedLength(pszFormat, args);
    wchar_t* pszBuffer = new wchar_t[nLength + 1];
    ::ZeroMemory(pszBuffer, nLength + 1);
    Format(pszBuffer, nLength + 1, pszFormat, args);
    std::wstring::operator=(std::wstring(pszBuffer));
    delete []pszBuffer;
}

int String::GetFormattedLength( const wchar_t* pszFormat, va_list args )
{
    return _vscwprintf(pszFormat, args);
}

以上代码在VS2008编译通过。

posted @ 2015-07-29 18:23 weigtcs 阅读(1281) | 评论 (0)编辑 收藏
  2015年4月27日
通过使用Sysinternals的procexp.exe工具提供的Process Explorer Search(菜单->Find->Find Handle or Dll或Ctrl+F)功能,我们可以看到某个文件正在被哪些进程使用。这个功能在你想删除某个文件,而系统提示“该文件正在被占用,不能删除”的时候非常有用。


posted @ 2015-04-27 23:28 weigtcs 阅读(309) | 评论 (0)编辑 收藏
  2015年3月19日
在使用Gdiplus的功能之前,要先进行初始化,对应的函数是Gdiplus::GdiplusStartup,在使用完Gdiplus的功能之后,要进行反初始化,对应的函数则是Gdiplus::GdiplusShutdown。
为了简化编程,这里实现了一个简单的Gdiplus初始化类,作为全局对象使用,类似于MFC的theApp对象。代码如下:
#pragma once

#include <GdiPlus.h>

class GdiPlusHelper
{
public:
    GdiPlusHelper()
    {
        Gdiplus::GdiplusStartupInput gdiplusStartupInput;
        Gdiplus::GdiplusStartup(&m_nGdiPlusToken, &gdiplusStartupInput, NULL);
    }
    ~GdiPlusHelper()
    {
        Gdiplus::GdiplusShutdown(m_nGdiPlusToken);
    }
    ULONG_PTR m_nGdiPlusToken;
};

posted @ 2015-03-19 15:14 weigtcs 阅读(213) | 评论 (0)编辑 收藏
  2015年3月18日
用Gdiplus::Matrix对图形进行简单的旋转,可以免除繁琐的数学计算。
这里主要用到了Gdiplus::Matrix::RotateAt和Gdiplus::Graphics::SetTransForm实现图形旋转。

1、类GdiPlus::Matrix的RotateAt方法,原型如下:
Status RotateAt( REAL angle,
    const PointF &center,
    MatrixOrder order
);
参数angle为需要旋转的角度,center为旋转的中心,order为旋转Matrix的顺序。order的取值有两个:Gdiplus::MatrixOrderPrepend和Gdiplus::MatrixOrderAppend,默认取值为Gdiplus::MatrixOrderPrepend。

2、类Gdiplus::Graphics的SetTransForm方法,原型如下:
Status SetTransform( const Matrix *matrix
);
参数matrix就是上面的Gdiplus::Matrix对象指针。

示例代码如下:
VOID Example_Rotate(HDC hdc)
{
   Gdiplus::Graphics graphics(hdc);
   Gdiplus::Pen pen(Color(255, 0, 0, 255));
   Gdiplus::Matrix matrix;
   Gdiplus::PonitF P(50, 50);             // 旋转中心
   matrix.RotateAt(100.0f, P);               // 旋转100度
   graphics.SetTransform(&matrix);
   graphics.DrawEllipse(&pen, 0, 0, 100, 50); 
}

效果展示:


参考资料:MSDN
posted @ 2015-03-18 15:34 weigtcs 阅读(405) | 评论 (0)编辑 收藏
  2015年1月11日
在开发图形界面(GUI)程序时,对于无句柄的图形控件的框架,在编写响应消息的代码时,可以采用虚函数的方法,在界面框架基类里面调用这些函数,而在子类重写这些虚函数,就可以得到消息的响应。但是,由于windows的消息众多,对应需要编写的虚函数就有很多,这样无疑加大了资源开销,效率也降低。而在MFC消息映射框架里,没有使用虚函数,而是使用了一大堆宏,减少了内存开销,提高了效率。本文提取了MFC消息映射框架,将窗口(CWnd)换成自己的图元(Element),实现了与MFC相同形式的消息映射。
在本代码中,Element是所有界面元素的基类,地位相当与MFC的CWnd。
消息响应函数类型定义的枚举:
enum ESig
{
    ESig_end = 0,     // [marks end of message map]

    ESig_b_D_v,                // BOOL (CDC*)
    ESig_b_b_v,                // BOOL (BOOL)
    ESig_b_u_v,                // BOOL (UINT)
    ESig_b_h_v,                // BOOL (HANDLE)
    ESig_b_W_uu,                // BOOL (CWnd*, UINT, UINT)
    ESig_b_W_COPYDATASTRUCT,                // BOOL (CWnd*, COPYDATASTRUCT*)
    ESig_b_v_HELPINFO,        // BOOL (LPHELPINFO);
    ESig_CTLCOLOR,            // HBRUSH (CDC*, CWnd*, UINT)
    ESig_CTLCOLOR_REFLECT,    // HBRUSH (CDC*, UINT)
    ESig_i_u_W_u,                // int (UINT, CWnd*, UINT)  // ?TOITEM
    ESig_i_uu_v,                // int (UINT, UINT)
    ESig_i_W_uu,                // int (CWnd*, UINT, UINT)
    ESig_i_v_s,                // int (LPTSTR)
    ESig_l_w_l,                // LRESULT (WPARAM, LPARAM)
    ESig_l_uu_M,                // LRESULT (UINT, UINT, CMenu*)
    ESig_v_b_h,                // void (BOOL, HANDLE)
    ESig_v_h_v,
   
};
这里只列举了部分响应函数类型。

基类消息映射函数回调函数定义:
typedef void (Element::*pEMsgFun)(void);

消息映射入口结构体,各个域的含义与MFC类似。
struct EMsgMap_Entery
{
    UINT nMessage;
    UINT nCode;
    UINT nID;
    UINT nLastID;
    UINT_PTR nSig;
    pEMsgFun pfn;
};

消息映射列表结构体。
struct EMsgMap
{
    const EMsgMap* (*pfnGetMessageMap)();
    const EMsgMap_Entery* lpEnteries;
};

消息映射声明与定义。
#define BEGIN_EMSG_MAP(theClass)\
    const EMsgMap* theClass::GetMessageMap() const\
return GetThisMessageMap(); }\
    const EMsgMap* theClass::GetThisMessageMap()\
{\
    typedef theClass ThisClass;\
    static const EMsgMap_Entery _messageEntries[]=\
{

#define END_EMSG_MAP()\
{0, 0, 0, 0, ESig_end, (pEMsgFun)0}\
};\
    static const EMsgMap messageMap=\
{ 0, &_messageEntries[0] };\
    return &messageMap;\
    \
}

部分已经实现的消息映射。
#define ON_EM_PAINT() \
{ WM_PAINT, 0, 0, 0, ESig_vv, \
    (pEMsgFun) \
    (static_cast< void (Element::*)(void) > ( &ThisClass :: OnPaint)) },

#define ON_EM_LBUTTONDOWN()\
{WM_LBUTTONDOWN, 0, 0, 0, ESig_vwp,\
    (pEMsgFun)\
    (static_cast<void(Element::*)(UINT, POINT)>(&ThisClass::OnLButtonDown))},

#define ON_EM_LBUTTONUP() \
{ WM_LBUTTONUP, 0, 0, 0, ESig_vwp, \
    (pEMsgFun) \
    (static_cast< void ( Element::*)(UINT, POINT) > ( &ThisClass :: OnLButtonUp)) },


#define ON_EM_MOUSEMOVE() \
{ WM_MOUSEMOVE, 0, 0, 0, ESig_vwp, \
    (pEMsgFun) \
    (static_cast< void ( Element::*)(UINT, POINT) > ( &ThisClass :: OnMouseMove)) },

#define ON_EM_MOUSELEAVE() \
{ WM_MOUSELEAVE, 0, 0, 0, ESig_vv, \
    (pEMsgFun) \
    (static_cast< void (Element::*)(void) > ( &ThisClass :: OnMouseLeave)) },

#define ON_EM_SIZE() \
{ WM_SIZE, 0, 0, 0, ESig_vwii, \
    (pEMsgFun) \
    (static_cast< void ( Element::*)(UINT, intint) > ( &ThisClass :: OnSize)) },

#define efx_msg

消息处理过程函数,只实现了部分。
LRESULT Element::HandleMessage( UINT uMsg, WPARAM wParam, LPARAM lParam )
{
    const EMsgMap* pMsgMap = GetMessageMap();
    if (pMsgMap == NULL)
        return false;
    const EMsgMap_Entery* pEntry = pMsgMap->lpEnteries;
    int i = 0;
    while(pEntry[i].nSig != ESig_end)
    {
        if (pEntry[i].nMessage == uMsg)
        {
            switch(pEntry[i].nSig)
            {
            case ESig_vwp:
                {
                    POINT pt;
                    pt.x = LOWORD(lParam);
                    pt.y = HIWORD(lParam);
                    (this->*(reinterpret_cast<void(Element::*)(UINT, POINT)>(pEntry[i].pfn)))((UINT)wParam, pt);
                    break;
                }
            case ESig_vv:
                {
                    (this->*(reinterpret_cast<void(Element::*)()>(pEntry[i].pfn)))();
                    break;
                }
            case ESig_vwii:
                {
                    (this->*(reinterpret_cast<void(Element::*)(UINT, intint)>(pEntry[i].pfn)))((UINT)wParam, LOWORD(lParam), HIWORD(lParam));
                    break;
                }
            default:
                ;
            }
        }
        i++;
    }

    return 1;
}

使用方法。
声明:
class Element
{
//
DECLARE_EMSG_MAP();
//

protected:
    efx_msg void OnPaint();
    efx_msg void OnMouseMove(UINT nFlag, POINT pt);
    efx_msg void OnMouseLeave();
    efx_msg void OnLButtonDown(UINT uFlag, POINT pt);
    efx_msg void OnLButtonUp(UINT uFlag, POINT pt);
//
};

实现:
BEGIN_EMSG_MAP(Element)
    //{
    ON_EM_PAINT()
    ON_EM_MOUSEMOVE()
    ON_EM_MOUSELEAVE()
    ON_EM_LBUTTONDOWN()
    ON_EM_LBUTTONUP()
    //}
END_EMSG_MAP()
void Element::OnMouseMove( UINT nFlag, POINT pt )
{
    TRACE(TEXT("%ld::Element::OnMouseMove"), this);
}

void Element::OnMouseLeave()
{
    TRACE(TEXT("%ld::Element::OnMouseLeave"), this);
}

void Element::OnLButtonDown( UINT uFlag, POINT pt )
{
    TRACE(TEXT("%ld::Element::OnLButtonDown"), this);
}

void Element::OnLButtonUp( UINT uFlag, POINT pt )
{
    TRACE(TEXT("%ld::Element::OnLButtonUp"), this);
}

这样可以按照以上的思路,不断完善消息映射函数类型。
由于Element是无窗口的图元元素,没有系统的窗口消息的分发支持,所以要想真正实现这些功能,还需要一个图元管理器,用于度量的坐标,消息的分发等等。

posted @ 2015-01-11 20:00 weigtcs 阅读(189) | 评论 (0)编辑 收藏
仅列出标题