taocoding


  • 首页

  • 关于

  • 标签

  • 分类

  • 归档

使用TinyXML解析XML

发表于 2009-06-08 | 分类于 C++

      由于工作需要,以前都是直接硬写在程序中的堆砌代码,现在决定都改为XML描述了,一来程序看起来清爽多了,二来以后扩展也方便。项目中使用的是TinyXML,今天去其官方网站逛了一圈,其中有个Tutorial写的很好,最后有个例子代码,个人感觉稍作修改完全可以拿到实际项目中使用,管他有多少个Node一个递归即搞定:

// tutorial demo program

#include “stdafx.h”

#include “tinyxml.h”

// ———————————————————————-
// STDOUT dump and indenting utility functions
// ———————————————————————-
const unsigned int NUM_INDENTS_PER_SPACE=2;

const char getIndent( unsigned int numIndents )
{
static const char
pINDENT=” + “;
static const unsigned int LENGTH=strlen( pINDENT );
unsigned int n=numIndents*NUM_INDENTS_PER_SPACE;
if ( n > LENGTH ) n = LENGTH;

return &pINDENT[ LENGTH-n ];
}

// same as getIndent but no “+” at the end
const char getIndentAlt( unsigned int numIndents )
{
static const char
pINDENT=” “;
static const unsigned int LENGTH=strlen( pINDENT );
unsigned int n=numIndents*NUM_INDENTS_PER_SPACE;
if ( n > LENGTH ) n = LENGTH;

return &pINDENT[ LENGTH-n ];
}

int dump_attribs_to_stdout(TiXmlElement* pElement, unsigned int indent)
{
if ( !pElement ) return 0;

TiXmlAttribute pAttrib=pElement->FirstAttribute();
int i=0;
int ival;
double dval;
const char
pIndent=getIndent(indent);
printf(“/n”);
while (pAttrib)
{
printf( “%s%s: value=[%s]”, pIndent, pAttrib->Name(), pAttrib->Value());

if (pAttrib->QueryIntValue(&ival)==TIXML_SUCCESS) printf( “ int=%d”, ival);
if (pAttrib->QueryDoubleValue(&dval)==TIXML_SUCCESS) printf( “ d=%1.1f”, dval);
printf( “/n” );
i++;
pAttrib=pAttrib->Next();
}
return i;
}

void dump_to_stdout( TiXmlNode* pParent, unsigned int indent = 0 )
{
if ( !pParent ) return;

TiXmlNode pChild;
TiXmlText
pText;
int t = pParent->Type();
printf( “%s”, getIndent(indent));
int num;

switch ( t )
{
case TiXmlNode::DOCUMENT:
printf( “Document” );
break;

case TiXmlNode::ELEMENT:
printf( “Element [%s]”, pParent->Value() );
num=dump_attribs_to_stdout(pParent->ToElement(), indent+1);
switch(num)
{
case 0: printf( “ (No attributes)”); break;
case 1: printf( “%s1 attribute”, getIndentAlt(indent)); break;
default: printf( “%s%d attributes”, getIndentAlt(indent), num); break;
}
break;

case TiXmlNode::COMMENT:
printf( “Comment: [%s]”, pParent->Value());
break;

case TiXmlNode::UNKNOWN:
printf( “Unknown” );
break;

case TiXmlNode::TEXT:
pText = pParent->ToText();
printf( “Text: [%s]”, pText->Value() );
break;

case TiXmlNode::DECLARATION:
printf( “Declaration” );
break;
default:
break;
}
printf( “/n” );
for ( pChild = pParent->FirstChild(); pChild != 0; pChild = pChild->NextSibling())
{
dump_to_stdout( pChild, indent+1 );
}
}

// load the named file and dump its structure to STDOUT
void dump_to_stdout(const char* pFilename)
{
TiXmlDocument doc(pFilename);
bool loadOkay = doc.LoadFile();
if (loadOkay)
{
printf(“/n%s:/n”, pFilename);
dump_to_stdout( &doc ); // defined later in the tutorial
}
else
{
printf(“Failed to load file /“%s/“/n”, pFilename);
}
}

// ———————————————————————-
// main() for printing files named on the command line
// ———————————————————————-
int main(int argc, char* argv[])
{
for (int i=1; i<argc; i++)
{
dump_to_stdout(argv[i]);
}
return 0;
}

递归和树简直就是绝配,前阵子做等了部分加载联系人到树控件时也是用递归搞定的,有时间再把递归好好研究下。

滚动条-可滚动文字的窗口

发表于 2009-05-30 | 分类于 VC

      就像玩War3时对不死族的恐惧一样,做界面时一直都不想去涉及滚动条,借端午节狠下心来把滚动条又看了一遍,再一次印证实践才是真理,把对滚动条的理解写下来,以便于以后查阅。

 

滚动条结构.gif)

上图是MSDN中对滚动条的描述,很直观,而滚动条相关的消息也不多最常用的也就是WM_VSCROLL和WM_HSCROLL,这两个消息的LOWORD (wParam)参数对应了一系列Request Code:


































































Request



Action



Response



SB_LINEUP



The user clicks the top scroll arrow.



Decrements the scroll box position; scrolls toward the top of the data by one unit.



SB_LINEDOWN



The user clicks the bottom scroll arrow.



Increments the scroll box position; scrolls toward the bottom of the data by one unit.



SB_LINELEFT



The user clicks the left scroll arrow.



Decrements the scroll box position; scrolls toward the left end of the data by one unit.



SB_LINERIGHT



The user clicks the right scroll arrow.



Increments the scroll box position; scrolls toward the right end of the data by one unit.



SB_PAGEUP



The user clicks the scroll bar shaft above the scroll box.



Decrements the scroll box position by the number of data units in the window; scrolls toward the top of the data by the same number of units.



SB_PAGEDOWN



The user clicks the scroll bar shaft below the scroll box.



Increments the scroll box position by the number of data units in the window; scrolls toward the bottom of the data by the same number of units.



SB_PAGELEFT



The user clicks the scroll bar shaft to the left of the scroll box.



Decrements the scroll box position by the number of data units in the window; scrolls toward the left end of the data by the same number of units.



SB_PAGERIGHT



The user clicks the scroll bar shaft to the right of the scroll box.



Increments the scroll box position by the number of data units in the window; scrolls toward the right end of the data by the same number of units.



SB_THUMBPOSITION



The user releases the scroll box after dragging it.



Sets the scroll box to the position specified in the message; scrolls the data by the same number of units the scroll box has moved.



SB_THUMBTRACK



The user drags the scroll box.



Sets the scroll box to the position specified in the message and scrolls the data by the same number of units the scroll box has moved for applications that draw data quickly. Applications that cannot draw data quickly must wait for the SB_THUMBPOSITION request code before moving the scroll box and scrolling the data.



SB_ENDSCROLL



The user releases the mouse after holding it on an arrow or in the scroll bar shaft.



No response is needed.

1**设置滚动条参数**

一般都是在WM_SIZE消息中设置滚动条的信息,这样当窗口大小变化时滚动条可以做相应的改变,以显示或者隐藏之或者改变其ScrollBox的大小。

MSDN上面有一段说道滚动条的显示问题:

Scroll Bar Visibility

The system hides and disables a standard scroll bar when equal minimum and maximum values are specified. The system also hides and disables a standard scroll bar if you specify a page size that includes the entire scroll range of the scroll bar. This is the way to temporarily hide a scroll bar when it is not needed for the content of the client area. There is no need to make scrolling requests through the scroll bar when it is hidden. The system enables the scroll bar and shows it again when you set the minimum and maximum values to unequal values or when the page size that does not include the entire scroll range. The ShowScrollBar function can also be used to hide or show a scroll bar. It does not affect the scroll bar’s range, page size, or scroll box position.

The EnableScrollBar function can be used to disable one or both arrows of a scroll bar. An application displays disabled arrows in gray and does not respond to user input.

红色标记的地方说道,系统会在两种情况下隐藏并禁用滚动条,1是在SCROLLINFO中的nMin==nMax时,由于最小滚动位置和最大滚动位置相等当然没有必要显示滚动条了,2是在指定的nPage,也就是当前窗口客户区可以显示的单位数据的大小,包含整个滚动范围,这时当前客户区可以显示所有的数据,因此不需要滚动条。MSDN上面是这样描述page size的:

page size代表滚动条的Ower窗口的当前客户区大小可以容纳单位数据的大小,例如如果客户区可以容纳16行文字,那么应该将page size设置为16,系统使用page size,以及滚动范围以及滚动条长度,来设置scroll box的大小,当一个包含滚动条的窗口改变大小时,应该通过SetScrollInfo设置page size。

2**滚动窗口**

进行窗口滚动的操作是在WM_VSCROLL或者WM_HSCROLL中完成的,先根据相应的Request Code对nPos进行调整,然后调用SetScrollInfo对nPos这一项进行调整,之后通过ScrollWindowEx滚动窗口,根据MSDN上面的例子可以看出,先保存先前的nPos,然后用调整后的nPos与之想减,再乘上水平或者垂直方向的单位尺寸,即为滚动的区域。

3**滚动后可见的窗口区域的绘制**

当窗口滚动后,面对的首要问题就是如何显示之前不可见现在可见的区域,对于滚动文字,需要处理当然是需要WM_PAINT了。这里看得不是很懂,但是通过TRACE可以发现的是WM_PAINT确实是在Invalide区域中重绘,当单击垂直滚动条的三角按钮时系统只重绘一行文字,具体方法可以看下面的源码。

下面的源码是MSDN的例子:

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)

{

      int wmId, wmEvent;

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

      HDC hdc;

      PAINTSTRUCT ps;

      TEXTMETRIC tm;

      SCROLLINFO si;

 

      // These variables are required to display text.

      static int xClient;     // width of client area

      static int yClient;     // height of client area

      static int xClientMax;  // maximum width of client area

 

      static int xChar;       // horizontal scrolling unit

      static int yChar;       // vertical scrolling unit

      static int xUpper;      // average width of uppercase letters

 

      static int xPos;        // current horizontal scrolling position

      static int yPos;        // current vertical scrolling position

 

      int i;                  // loop counter

      int x, y;               // horizontal and vertical coordinates

 

      int FirstLine;          // first line in the invalidated area

      int LastLine;           // last line in the invalidated area

      HRESULT hr;

      size_t  abcLength=0;       // length of an abc[] item

      // Create an array of lines to display.

      #define LINES 28

      static TCHAR *abc[] = {

           TEXT(“anteater”),  TEXT(“bear”),      TEXT(“cougar”),

           TEXT(“dingo”),     TEXT(“elephant”),  TEXT(“falcon”),

           TEXT(“gazelle”),   TEXT(“hyena”),     TEXT(“iguana”),

           TEXT(“jackal”),    TEXT(“kangaroo”),  TEXT(“llama”),

           TEXT(“moose”),     TEXT(“newt”),      TEXT(“octopus”),

           TEXT(“penguin”),   TEXT(“quail”),     TEXT(“rat”),

           TEXT(“squid”),     TEXT(“tortoise”),  TEXT(“urus”),

           TEXT(“vole”),      TEXT(“walrus”),    TEXT(“xylophone”),

           TEXT(“yak”),       TEXT(“zebra”),

           TEXT(“This line contains words, but no character. Go figure.”),

           TEXT(“”)

      };

 

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

      switch (message)

      {

      case WM_CREATE:

           {

                 CreateWindowEx(

                      0L,                          // no extended styles

                      _T(“SCROLLBAR”),                 // scroll bar control class

                      (LPCWSTR) NULL,                // text for window title bar

                      WS_CHILD | SBS_HORZ,         // scroll bar styles

                      0,                           // horizontal position

                      0,                           // vertical position

                      200,                         // width of the scroll bar

                      50,               // default height

                      hWnd,                   // handle to main window

                      (HMENU) NULL,           // no menu for a scroll bar

                      hInst,                  // instance owning this window

                      (LPVOID) NULL           // pointer not needed

                      );

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

                 // Get the handle to the client area’s device context.

                 hdc = GetDC (hWnd);

                 // Extract font dimensions from the text metrics.

                 GetTextMetrics (hdc, &tm);

                 xChar = tm.tmAveCharWidth;

                 xUpper = (tm.tmPitchAndFamily & 1 ? 3 : 2) * xChar/2;

                 yChar = tm.tmHeight + tm.tmExternalLeading;

                 // Free the device context.

                 ReleaseDC (hWnd, hdc);

                 // Set an arbitrary maximum width for client area.

                 // (xClientMax is the sum of the widths of 48 average

                 // lowercase letters and 12 uppercase letters.)

                 xClientMax = 48 xChar + 12 xUpper;

                 return 0;

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

           }

      case WM_COMMAND:

           wmId    = LOWORD(wParam);

           wmEvent = HIWORD(wParam);

           // 分析菜单选择:

           switch (wmId)

           {

           case IDM_ABOUT:

                 DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);

                 break;

           case IDM_EXIT:

                 DestroyWindow(hWnd);

                 break;

           default:

                 return DefWindowProc(hWnd, message, wParam, lParam);

           }

           break;

      case WM_SIZE:

           {

                 // Retrieve the dimensions of the client area.

                 yClient = HIWORD (lParam);

                 xClient = LOWORD (lParam);

 

                 // Set the vertical scrolling range and page size

                 si.cbSize = sizeof(si);

                 si.fMask  = SIF_RANGE | SIF_PAGE;

                 si.nMin   = 0;

                 si.nMax   = LINES - 1;

                 si.nPage  = yClient / yChar;

                 SetScrollInfo(hWnd, SB_VERT, &si, TRUE);

 

                 // Set the horizontal scrolling range and page size.

                 si.cbSize = sizeof(si);

                 si.fMask  = SIF_RANGE | SIF_PAGE;

                 si.nMin   = 0;

                 si.nMax   = 2 + xClientMax / xChar;

                 si.nPage  = xClient / xChar;

                 SetScrollInfo(hWnd, SB_HORZ, &si, TRUE);

                 return 0;

           }

      case WM_HSCROLL:

           {

                 // Get all the vertial scroll bar information

                 si.cbSize = sizeof (si);

                 si.fMask  = SIF_ALL;

                 // Save the position for comparison later on

                 GetScrollInfo (hWnd, SB_HORZ, &si);

                 xPos = si.nPos;

                 switch (LOWORD (wParam))

                 {

                      // user clicked left arrow

                 case SB_LINELEFT:

                      si.nPos -= 1;

                      break;

                      // user clicked right arrow

                 case SB_LINERIGHT:

                      si.nPos += 1;

                      break;

                      // user clicked the scroll bar shaft left of the scroll box

                 case SB_PAGELEFT:

                      si.nPos -= si.nPage;

                      break;

                      // user clicked the scroll bar shaft right of the scroll box

                 case SB_PAGERIGHT:

                      si.nPos += si.nPage;

                      break;

                      // user dragged the scroll box

                 case SB_THUMBTRACK:

                      si.nPos = si.nTrackPos;

                      break;

                 default :

                      break;

                 }

                 // Set the position and then retrieve it.  Due to adjustments

                 //   by Windows it may not be the same as the value set.

                 si.fMask = SIF_POS;

                 SetScrollInfo (hWnd, SB_HORZ, &si, TRUE);

                 GetScrollInfo (hWnd, SB_HORZ, &si);

 

                 // If the position has changed, scroll the window

                 if (si.nPos != xPos)

                 {

                      ScrollWindowEx(hWnd, xChar * (xPos - si.nPos), 0, NULL, NULL,

                             NULL, NULL,SW_INVALIDATE|SW_ERASE);

                      //ScrollWindow(hWnd, xChar * (xPos - si.nPos), 0, NULL, NULL);

                 }

                 return 0;

           }

      case WM_VSCROLL:

           {

                 // Get all the vertial scroll bar information

                 si.cbSize = sizeof (si);

                 si.fMask  = SIF_ALL;

                 GetScrollInfo (hWnd, SB_VERT, &si);

                 // Save the position for comparison later on

                 yPos = si.nPos;

                 switch (LOWORD (wParam))

                 {

                      // user clicked the HOME keyboard key

                 case SB_TOP:

                      si.nPos = si.nMin;

                      break;

 

                      // user clicked the END keyboard key

                 case SB_BOTTOM:

                      si.nPos = si.nMax;

                      break;

 

                      // user clicked the top arrow

                 case SB_LINEUP:

                      si.nPos -= 1;

                      break;

 

                      // user clicked the bottom arrow

                 case SB_LINEDOWN:

                      si.nPos += 1;

                      break;

 

                      // user clicked the scroll bar shaft above the scroll box

                 case SB_PAGEUP:

                      si.nPos -= si.nPage;

                      break;

 

                      // user clicked the scroll bar shaft below the scroll box

                 case SB_PAGEDOWN:

                      si.nPos += si.nPage;

                      break;

 

                      // user dragged the scroll box

                 case SB_THUMBTRACK:

                      si.nPos = si.nTrackPos;

                      break;

 

                 default:

                      break;

                 }

                 // Set the position and then retrieve it.  Due to adjustments

                 //   by Windows it may not be the same as the value set.

                 si.fMask = SIF_POS;

                 SetScrollInfo (hWnd, SB_VERT, &si, TRUE);

                 GetScrollInfo (hWnd, SB_VERT, &si);

                 // If the position has changed, scroll window and update it

                 if (si.nPos != yPos)

                 {                   

                      ScrollWindow(hWnd, 0, yChar * (yPos - si.nPos), NULL, NULL);

                      UpdateWindow (hWnd);

                 }

                 return 0;

           }

      case WM_PAINT:

           {

                 // Prepare the window for painting

                 hdc = BeginPaint (hWnd, &ps);

                 // Get vertical scroll bar position

                 si.cbSize = sizeof (si);

                 si.fMask  = SIF_POS;

                 GetScrollInfo (hWnd, SB_VERT, &si);

                 yPos = si.nPos;

                 // Get horizontal scroll bar position

                 GetScrollInfo (hWnd, SB_HORZ, &si);

                 xPos = si.nPos;

                 // Find painting limits

                 FirstLine = max (0, yPos + ps.rcPaint.top / yChar);

                 LastLine = min (LINES - 1, yPos + ps.rcPaint.bottom / yChar);

                 sprintf(szDebug,(“%d,%d,%d,%d/r/n”),ps.rcPaint.left,ps.rcPaint.top,ps.rcPaint.right,ps.rcPaint.bottom);

                 OutputDebugStringA(szDebug);

                 ZeroMemory(szDebug,0);

      sprintf(szDebug,“FirstLine=%d,LastLine=%d/r/n”,FirstLine,LastLine);

                 OutputDebugStringA(szDebug);

                 for (i = FirstLine; i <= LastLine; i++)

                 {

                      x = xChar * (1 - xPos);

                      y = yChar * (i - yPos);

                      // Note that “55” in the following depends on the

                      // maximum size of an abc[] item.

                      //

                      hr = StringCchLength(abc[i], 100, &abcLength);

                      if ((FAILED(hr)) | (&abcLength == NULL))

                      {

                            /MessageBox(hWnd,_T(“字符串长度为!”),_T(“错误“),MB_ICONERROR);/

                      }

                      else

                      {

                            TextOut(hdc,x,y,abc[i],abcLength);

                      }

                 }

                 // Indicate that painting is finished

                 EndPaint (hWnd, &ps);

                 return 0;

           }

      case WM_DESTROY:

           PostQuitMessage(0);

           break;

      default:

           return DefWindowProc(hWnd, message, wParam, lParam);

      }

      return 0;

}

Function object And Binders

发表于 2009-05-18 | 分类于 C++

这两个概念一般都是一起出现的,今天再次翻起《Ruminations On C++》,这两个概念真的如Koenig所说比较难以理解,加上这次我以前至少也看过了3次了,但是每次都是当时看懂了,过后就忘了,究其原因1:没有真正理解;2没有应用到实际中。

    现在暂时也不会应用到实际,但是这次的理解必须写下来。其实函数对象倒还好,一个重载了()了类其对象基本上就可以叫做函数对象,Koenig的说法是:函数对象提供了一种方法,将要调用的函数与准备传递给这个函数的隐式参数捆绑起来。

template<typename _Arg1, typename _Arg2, typename _Result>

    struct binary_function

    {

      typedef _Arg1 first_argument_type;   ///< the type of the first argument

                                       ///  (no surprises here)

      typedef _Arg2 second_argument_type;  ///< the type of the second argument

      typedef _Result result_type;         ///< type of the return type

    };

 

template<typename _Tp>

    struct greater : public binary_function<_Tp, _Tp, bool>

    {

      bool

      operator()(const _Tp& x, const _Tp& y) const

      { return x > y; }

};

有了greater我们就可以定义一个对象

greater<int> gt;

bool greater1000(int n)

{

return gt(n,1000);//这里就是调用了greater的operator()

}

bind2nd可以将一个二元函数对象f(x,y)中的第二个参数y绑定到一个新的一元函数对象上g(x),这时通过g(x)(y)即相当于f(x,y)了,真是妙,这不就是数学里面的复合函数,这次是第一次领悟到这一点,也算是一点进步吧。通过bind2nd的源码可以很清晰得看出其内部机理:

template<typename _Operation>

    class binder2nd

    : public unary_function<typename _Operation::first_argument_type,

    typename _Operation::result_type>

    {

    protected:

      _Operation op;

      typename _Operation::second_argument_type value;

 

    public:

      binder2nd(const _Operation& __x,

const typename _Operation::second_argument_type& __y)

      : op(x), value(y) { }

      //下面的()重载即相当于f(x,y)了,只不过这时的y已经是binder2nd对象的一个成员了,当然f也是起一个成员,这样外部只需传递x了,即将binary转换为unary了。

      typename _Operation::result_type

      operator()(const typename _Operation::first_argument_type& __x) const

      { return op(__x, value); }

 

      // _GLIBCXX_RESOLVE_LIB_DEFECTS

      // 109.  Missing binders for non-const sequence elements

      typename _Operation::result_type

      operator()(typename _Operation::first_argument_type& __x) const

      { return op(__x, value); }

    } _GLIBCXX_DEPRECATED_ATTR;

 

  /// One of the @link s20_3_6_binder binder functors@endlink.

  template<typename _Operation, typename _Tp>

    inline binder2nd<_Operation>

    bind2nd(const _Operation& fn, const _Tp& x)

    {

      typedef typename _Operation::second_argument_type _Arg2_type;

      return binder2nd01<_Operation>(fn, _Arg2_type(x));

} 

下面来看看MSDN上面的一个例子:

// functional_bind2nd.cpp

// compile with: /EHsc

#include <vector>

#include <functional>

#include <algorithm>

#include <iostream>

using namespace std;

// Creation of a user-defined function object

// that inherits from the unary_function base class

//定义一个一元函数对象,判定传入的参数是否是大于15

class greaterthan15: unary_function<int, bool>

{

public:

    result_type operator()(argument_type i)

    {

        return (result_type)(i > 15);

    }

};

int main()

{

    vector<int> v1;

    vector<int>::iterator Iter;

    int i;

    for (i = 0; i <= 5; i++)

    {

        v1.push_back(5 * i);

    }

    cout << ”The vector v1 = ( ”;

    for (Iter = v1.begin(); Iter != v1.end(); Iter++)

        cout << *Iter << ” ”;

    cout << ”)” << endl;

    // Count the number of integers > 10 in the vector

vector<int>::iterator::difference_type result1a;

//将10绑定到新的函数对象binder2nd(greater<int>(),10)上面,接着通过count_if来迭代,并传递参数(v1.begin()),也就是实现对每一个元素调用greater<int>(v1.begin(),10)

    result1a = count_if(v1.begin(), v1.end(), bind2nd(greater<int>(), 10));

    cout << ”The number of elements in v1 greater than 10 is: ”

         << result1a << ”.” << endl;

 

    // Compare counting the number of integers > 15 in the vector

    // with a user-defined function object

vector<int>::iterator::difference_type result1b;

//这里直接传入一元函数对象

    result1b = count_if(v1.begin(), v1.end(), greaterthan15());

    cout << ”The number of elements in v1 greater than 15 is: ”

         << result1b << ”.” << endl;

 

    // Count the number of integers < 10 in the vector

vector<int>::iterator::difference_type result2;

//将10绑定到新的函数对象binder2nd(greater<int>(),10)上面,只不过这时10是作为第一个参数绑定的,接着通过count_if来迭代,并传递参数(v1.begin()),也就是实现对每一个元素调用greater<int>(10,v1.begin()),也就是比10小的元素个数

    result2 = count_if(v1.begin(), v1.end(), bind1st(greater<int>(), 10));

    cout << ”The number of elements in v1 less than 10 is: ”

         << result2 << ”.” << endl;

}


电脑人多食枸杞子保护眼睛

发表于 2009-05-17 | 分类于 生活轨迹
<div class="content">![](http://imgsrc.baidu.com/baike/abpic/item/d002b34bd6faa2d283025c28.jpg)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </div>
      电脑人多食营养眼睛的食物,你在工作中经常使用电脑吗?眼睛有干涩、血丝、怕光,流泪,甚至红肿的现象吗?如果有,说明你的眼睛已经受到了伤害。眼睛疲倦的原因一般与眼泪的分泌有关,这要引起你的重视,并要加倍保护眼睛,而如果能在饮食中加入一些营养眼睛的食物,是最方便最有效的方法。

维他命A不用多说,素有”护眼之必需”之称是预防眼干、视力衰退、夜盲症的良方,以胡萝卜及绿、黄的蔬菜及红枣含量最多。维他命B,是视觉神经的营养来源之一,维他命B1不足,眼睛容易疲劳;维他命B2不足,容易引起角膜炎。可以多吃些芝麻、大豆、鲜奶、小麦胚芽等食物。枸杞子清肝明目的疗效大家早已知道,因为它含有丰富的胡萝卜素,维他命A、B1、B2、C、钙、铁等,是健康眼睛的必需营养。

枸杞子的三种食疗配方:1. 枸杞子+米:煮成粥后,加入一点白糖,能够治疗视力模糊及流泪的现象。2. 枸杞子+菊花:用热水冲泡饮用,能使眼睛轻松、明亮。3. 枸杞子+猪肝:煲汤具有清热、消除眼涩、消除因熬夜出现的黑眼圈。决明子具有清肝明目及润肠的功效,能改善眼睛肿痛、红赤多泪,防止视力减弱。

Neat Stuff Custom Draw

发表于 2009-05-17 | 分类于 VC

      专门做界面已经有半年了,期间用得最多也就是Owner Draw,对于Cutom Draw只是知之一二,没有具体用过,其实Ower Draw用得最多也就是Button,ListBox两个,由于项目中有个同事把TreeCtrl进行Custom Draw了,效果很不错,这才意识到其强大及易用,相比较而言Ower Draw就复杂多了,今天再次把CP上那篇经典的关于Custom Draw文章看了一篇,用了半个小时写了Slider的Custom Draw,也算是为了练习使用WTL和GDI+:

class CCDSliderCtrl :  public CWindowImpl<CCDSliderCtrl,CTrackBarCtrl>,
public CCustomDraw<CCDSliderCtrl>
{
public:
BEGIN_MSG_MAP(CCDSliderCtrl)    
CHAIN_MSG_MAP_ALT(CCustomDraw< CCDSliderCtrl >, 1)
DEFAULT_REFLECTION_HANDLER()
END_MSG_MAP()
public:
CCDSliderCtrl():m_pImageThumb(NULL),m_pImageChannel(NULL)
{

}
~CCDSliderCtrl()
{
if (NULL!=m_pImageThumb)
{
delete m_pImageThumb;
m_pImageThumb=NULL;
}

if (NULL!=m_pImageChannel)
{
delete m_pImageChannel;
m_pImageChannel=NULL;
}
}
void SetImage(LPCTSTR lpszThumb,LPCTSTR lpszChannel)
{
if (NULL!=m_pImageThumb)
{
delete m_pImageThumb;
m_pImageThumb=NULL;
}
m_pImageThumb=new Image((WCHAR*)lpszThumb);

if (NULL!=m_pImageChannel)
{
delete m_pImageChannel;
m_pImageChannel=NULL;
}
m_pImageChannel=new Image((WCHAR*)lpszChannel);
}
DWORD OnPrePaint( int idCtrl, LPNMCUSTOMDRAW lpNMCustomDraw )
{
return CDRF_NOTIFYITEMDRAW;
}
DWORD OnItemPrePaint( int idCtrl, LPNMCUSTOMDRAW lpNMCustomDraw )
{
Graphics graphics(lpNMCustomDraw->hdc);
CRect rcThumb(lpNMCustomDraw->rc);

switch ( lpNMCustomDraw->dwItemSpec )
{
case TBCD_CHANNEL:
{
CRect rcClient;
GetClientRect( &rcClient);

ImageAttributes imAtt;
imAtt.SetColorKey(
Color(255, 0,255),
Color(255, 0,255),
ColorAdjustTypeBitmap);

graphics.DrawImage(
m_pImageChannel, 
Rect(0, 0, rcClient.Width(),rcClient.Height()),  // dest rect
0, 0, m_pImageChannel->GetWidth(),m_pImageChannel->GetHeight(),          // source rect
UnitPixel,
&imAtt);

break;
}

case TBCD_TICS:
return CDRF_DODEFAULT;
case TBCD_THUMB:
{
graphics.DrawImage(m_pImageThumb,Rect(rcThumb.left,rcThumb.top,rcThumb.Width(),rcThumb.Height()));

break;
}

default:
ATLASSERT( FALSE );
};

return CDRF_SKIPDEFAULT;
}
protected:
Gdiplus::Image* m_pImageThumb;
Gdiplus::Image* m_pImageChannel;
};

下面是效果图:

另一种界面闪烁解决方案

发表于 2009-05-15 | 分类于 VC

      基于贴图的界面中,为了实现界面的统一,一种方法就是所有界面类派上自一个贴图的基类,而基类中一般是进行最基本的贴图,派生类中多数会进行自己的其他绘制,这时如果不进行特殊处理必然会出现闪烁,因为基类和派生类不是一起绘制的,这里介绍一种方案避免闪烁,具体实现参看代码:

下面是基类,只是象征性的绘制了下:

#include <atlgdi.h>
#include <atlmisc.h>
template <class T>
class ATL_NO_VTABLE CFlickFreeBaseDlg : public CDialogImpl<T>
{
BEGIN_MSG_MAP_EX(CFlickFreeBaseDlg)
MSG_WM_PAINT(OnPaint)
MSG_WM_ERASEBKGND(OnEraseBkgnd)
END_MSG_MAP()
public:
CFlickFreeBaseDlg():m_pMemDC(NULL)
{

}
~CFlickFreeBaseDlg()
{
if (m_pMemDC)
{
delete m_pMemDC;
m_pMemDC=NULL;
}
}
protected:
void OnPaint(CDCHandle dc)
{
GetClientRect(&m_rcClient);
CPaintDC dcPaint(m_hWnd);
if (NULL==m_pMemDC)
{
m_pMemDC=new CMemoryDC(dcPaint,m_rcClient);
}
//Do Base Paint
m_pMemDC->FillSolidRect(m_rcClient,RGB(0,100,255));
m_pMemDC->DrawText(_T("Draw In Base"),-1,CRect(0,0,80,20),DT_SINGLELINE|DT_VCENTER);
static_cast<T*>(this)->DerivingDraw();
delete m_pMemDC;
m_pMemDC=NULL;
}
BOOL OnEraseBkgnd(CDCHandle dc)
{
return TRUE;
}
protected:
CRect     m_rcClient;
CMemoryDC *m_pMemDC;
};

下面是派生类代码:

#include “FlickFreeBase.h”
class CMainDlg : public CFlickFreeBaseDlg<CMainDlg>, public CUpdateUI<CMainDlg>,
public CMessageFilter, public CIdleHandler
{
public:
enum { IDD = IDD_MAINDLG };

virtual BOOL PreTranslateMessage(MSG* pMsg)
{
return CWindow::IsDialogMessage(pMsg);
}

virtual BOOL OnIdle()
{
return FALSE;
}

BEGIN_UPDATE_UI_MAP(CMainDlg)
END_UPDATE_UI_MAP()

BEGIN_MSG_MAP(CMainDlg)
CHAIN_MSG_MAP(CFlickFreeBaseDlg<CMainDlg>)
MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
COMMAND_ID_HANDLER(ID_APP_ABOUT, OnAppAbout)
COMMAND_ID_HANDLER(IDOK, OnOK)
COMMAND_ID_HANDLER(IDCANCEL, OnCancel)
END_MSG_MAP()

// Handler prototypes (uncomment arguments if needed):
//LRESULT MessageHandler(UINT /uMsg/, WPARAM /wParam/, LPARAM /lParam/, BOOL& /bHandled/)
//LRESULT CommandHandler(WORD /wNotifyCode/, WORD /wID/, HWND /hWndCtl/, BOOL& /bHandled/)
//LRESULT NotifyHandler(int /idCtrl/, LPNMHDR /pnmh/, BOOL& /bHandled/)

LRESULT OnInitDialog(UINT /uMsg/, WPARAM /wParam/, LPARAM /lParam/, BOOL& /bHandled/)
{
// center the dialog on the screen
CenterWindow();

// set icons
HICON hIcon = (HICON)::LoadImage(_Module.GetResourceInstance(), MAKEINTRESOURCE(IDR_MAINFRAME),
IMAGE_ICON, ::GetSystemMetrics(SM_CXICON), ::GetSystemMetrics(SM_CYICON), LR_DEFAULTCOLOR);
SetIcon(hIcon, TRUE);
HICON hIconSmall = (HICON)::LoadImage(_Module.GetResourceInstance(), MAKEINTRESOURCE(IDR_MAINFRAME),
IMAGE_ICON, ::GetSystemMetrics(SM_CXSMICON), ::GetSystemMetrics(SM_CYSMICON), LR_DEFAULTCOLOR);
SetIcon(hIconSmall, FALSE);

// register object for message filtering and idle updates
CMessageLoop* pLoop = _Module.GetMessageLoop();
ATLASSERT(pLoop != NULL);
pLoop->AddMessageFilter(this);
pLoop->AddIdleHandler(this);

UIAddChildWindowContainer(m_hWnd);

return TRUE;
}

LRESULT OnDestroy(UINT /uMsg/, WPARAM /wParam/, LPARAM /lParam/, BOOL& /bHandled/)
{
// unregister message filtering and idle updates
CMessageLoop* pLoop = _Module.GetMessageLoop();
ATLASSERT(pLoop != NULL);
pLoop->RemoveMessageFilter(this);
pLoop->RemoveIdleHandler(this);

return 0;
}

LRESULT OnAppAbout(WORD /wNotifyCode/, WORD /wID/, HWND /hWndCtl/, BOOL& /bHandled/)
{
CAboutDlg dlg;
dlg.DoModal();
return 0;
}

LRESULT OnOK(WORD /wNotifyCode/, WORD wID, HWND /hWndCtl/, BOOL& /bHandled/)
{
// TODO: Add validation code
CloseDialog(wID);
return 0;
}

LRESULT OnCancel(WORD /wNotifyCode/, WORD wID, HWND /hWndCtl/, BOOL& /bHandled/)
{
CloseDialog(wID);
return 0;
}

void CloseDialog(int nVal)
{
DestroyWindow();
::PostQuitMessage(nVal);
}

void DerivingDraw()
{
m_pMemDC->FillSolidRect(CRect(100,50,400,300),RGB(119,173,2));
m_pMemDC->DrawText(_T(“Draw In Deriving”),-1,CRect(100,50,400,300),DT_SINGLELINE|DT_VCENTER);
}
}; 

 

WTL8.1 发布了

发表于 2009-05-11 | 分类于 VC

http://sourceforge.net/projects/wtl/

 

应该是个好兆头。

头文件和Dll不一致导致的问题

发表于 2009-04-20 | 分类于 C++

      最近把年前那个项目全部重新编码,虽然对我来说多了点功能要做,但更多的还是界面,这次比上次更惨了,整个界面都得我一个人写,任何资源的添加都是我一个。这样有好也有坏,控制力度比较大,但是人也累得够呛。

      前段时间把登陆部分的功能搞定了,这不又重操旧业了,搞了一天终于把界面闪烁和透明子控件搞得差不多了,今天从办公室一同事那学到一招,哎,这就是经验的体现,由于Leader不让我把一工程添加进去(这个工程差全是界面方面的,所以只有我一个人使用),每次都是把dll和头文件拷过去,今天搞得昏了,有一次忘了拷.h文件,只把dll拷过去了,结果就出问题了:

同样的“代码”运行确不同,代码执行的路径出现偏差,具体原因应该就是函数地址的偏移吧,那同事调了一会就指出,恍然大悟,更新.h果然就OK 了,这个问题太隐蔽了,头文件不一致导致函数地址的偏移,完全没有编译期的错误警告提示!

复制对象时勿忘其每一个成分

发表于 2009-04-19 | 分类于 C++

前言:看了好久Effective,但是感觉好多都是看了就忘,现在再看一边,顺便把一些易忘的记录下来,争取每天一记。

概念:Copying函数,包括copy constructor;copy assignment operator,对于默认的编译器生成版,会将被拷贝的对象的所有成员变量都做一份拷贝。

如果你自己声明一个copying函数,编译器就会以一种奇怪的方式回应:当你的实现代码几乎必然出错时却不告诉你.(不知道是作者原话还是译者,感觉挺有意思的)

该条款有两个需要注意的地方:1复制所有local成员变量2调用所有base classes内的copying函数。

第一个地方还好,比较容易理解,下面主要讲讲第二个->

 

 



view plaincopy to clipboardprint?

  1. void logCall(const std::string& funcName);          // make a log entry   
  2. class Customer {   
  3. public:   
  4.   …   
  5.   Customer(const Customer& rhs);   
  6.   Customer& operator=(const Customer& rhs);   
  7.   …   
  8. private:   
  9.   std::string name;   
  10. };   
  11.   
  12. Customer::Customer(const Customer& rhs)   
  13. : name(rhs.name)                                 // copy rhs’s data   
  14. {   
  15.   logCall(“Customer copy constructor”);   
  16. }   
  17.   
  18. Customer& Customer::operator=(const Customer& rhs)   
  19. {   
  20.   logCall(“Customer copy assignment operator”);   
  21.   name = rhs.name;                                  
  22.   return *this;                                     
  23. }   
  24.   
  25. class Date { … };       // for dates in time   
  26.   
  27. class Customer {   
  28. public:   
  29.   …                     // as before   
  30. private:   
  31.   std::string name;   
  32.   Date lastTransaction;   
  33. };   
  34.   
  35. class PriorityCustomer: public Customer {                  // a derived class   
  36. public:   
  37.    …   
  38.    PriorityCustomer(const PriorityCustomer& rhs);   
  39.    PriorityCustomer& operator=(const PriorityCustomer& rhs);   
  40.    …   
  41. private:   
  42.    int priority;   
  43. };   
  44.   
  45. PriorityCustomer::PriorityCustomer(const PriorityCustomer& rhs)   
  46. : priority(rhs.priority)   
  47. {   
  48.   logCall(“PriorityCustomer copy constructor”);   
  49. }   
  50. PriorityCustomer& PriorityCustomer::operator=(const PriorityCustomer& rhs)   
  51. {   
  52.   logCall(“PriorityCustomer copy assignment operator”);   
  53.   priority = rhs.priority;   
  54.   return *this;   
  55. }  

PriorityCustomer类的copying函数好像复制了PriorityCustomer内的每一样东西,它复制了PriorityCustomer声明的成员变量,但是其基类Customer成员变量却没有被复制(其实应该是没有按照相应的参数复制,而是使用了这些变量的default构造函数),这一点是尤其需要注意的,尤其是没有真正写过类似代码时很容易忽视这个问题,正确的写法是下面这样的:

 



view plaincopy to clipboardprint?

  1. PriorityCustomer::PriorityCustomer(const PriorityCustomer& rhs)   
  2. :Customer(rhs),                   // invoke base class copy ctor   
  3.  priority(rhs.priority)   
  4. {   
  5.   logCall(“PriorityCustomer copy constructor”);   
  6. }   
  7.   
  8.   
  9. PriorityCustomer& PriorityCustomer::operator=(const PriorityCustomer& rhs)   
  10. {   
  11.   logCall(“PriorityCustomer copy assignment operator”);   
  12.   Customer::operator=(rhs);           // assign base class parts   
  13.   priority = rhs.priority;   
  14.   return *this;   
  15. }  

具体内容见Items12。

WS_CLIPCHILDREN风格窗体控件透明的解决方案

发表于 2009-04-18 | 分类于 VC

在Windows下窗体都是矩形的,但是有时在做界面时尤其是需要贴图的界面中比如QQ2008(09另当别论),很多时候控件都是“非矩形”的,主要是因为图片不是矩形的,可能需要边角地方透明比如http://blog.csdn.net/ToCpp/archive/2009/01/22/3849541.aspx中按钮的边角就不是矩形的,这时如果窗体的样式没有WS_CLIPCHILDREN倒很好弄,如果有这个样式就麻烦了,因为这个样式会使父窗体不绘制子窗体的区域。说到这里其实也就自然而然有一种解决方案了:就是在绘制控件前先绘制父窗体的背景,刚刚发现一个相当简单的实现方法,DrawThemeParentBackground,这个函数刚好实现需求,不过前提是XP以上系统才能用。当然通过自己获取父窗体背景再绘制也是可以的,具体方案网上就很多了。

1…101112…16

billowqiu

157 日志
33 分类
10 标签
GitHub E-Mail
© 2020 billowqiu
由 Hexo 强力驱动
|
主题 — NexT.Pisces v5.1.3