锘??xml version="1.0" encoding="utf-8" standalone="yes"?>
AVLTree.h鏂囦歡
#ifndef AVL_TREE_H
#define AVL_TREE_H
#include <cassert>
#include <algorithm>
#ifdef _PRINT
#include <vector>
#include <iostream>
#include <memory>
#include <functional>
#endif // _PRINT
namespace ghost{
/// AVL鏍?
template<typename ComparableT>
class AVLTree{
public:
typedef ComparableT DataType;
private:
/// 鑺傜偣錛岀紦瀛樹簡鑷韓鐨勯珮搴?
struct Node_{
DataType data; // 鍙繘琛屾瘮杈冪殑鏁版嵁
Node_* pLeftChild; // 鎸囧悜宸﹀効瀛?
Node_* pRightChild; // 鎸囧悜鍙沖効瀛?
int height; // 浣滀負鏍硅妭鐐圭殑鏍戦珮搴︼紝
Node_()
: pLeftChild(0)
, pRightChild(0)
, height(0) // 綰﹀畾鍙跺瓙楂樺害涓?錛屾晠鑺傜偣楂樺害鍒濆鍖栦負0
{
}
explicit Node_(const DataType& d)
: data(d)
, pLeftChild(0)
, pRightChild(0)
, height(0) // 綰﹀畾鍙跺瓙楂樺害涓?錛屾晠鑺傜偣楂樺害鍒濆鍖栦負0
{
}
Node_(const Node_&) = delete;
Node_& operator =(const Node_&) = delete;
};
Node_* pRoot_; // 鎸囧悜鏍硅妭鐐?
public:
/// 榛樿鍒濆鍖栦負絀烘爲
AVLTree()
: pRoot_(0)
{
#ifdef _PRINT
std::cout<<"鍒涘緩AVL鏍?<<std::endl;
#endif // _PRINT
}
~AVLTree()
{
Clear();
}
AVLTree(const AVLTree&) = delete;
AVLTree& operator =(const AVLTree&) = delete;
public:
/// 鑾峰彇鏍戦珮搴︼紝絀烘爲榪斿洖-1錛屽彧鏈変釜鑺傜偣榪斿洖0
int GetHeight() const{return GetHeight_(pRoot_);}
#ifdef _PRINT
/// 鎵撳嵃鑰咃紝鍗抽渶瑕佹墦鍗扮殑瀵硅薄
class Printer{
public:
virtual ~Printer(){}
public:
virtual void Print() const{}
virtual bool IsValid() const{return false;}
};
typedef std::shared_ptr<Printer> PSharedPrinter; // 鎵撳嵃鑰呭叡浜寚閽?
typedef std::vector<PSharedPrinter> PrinterContainer; // 鎵撳嵃鑰呭叡浜寚閽堢殑瀹瑰櫒
/// 鑺傜偣鎵撳嵃鑰?
class NodePrinter : public Printer{
Node_* pNode_;
size_t width_;
PrinterContainer& nextPrinters_;
public:
NodePrinter(Node_* p, PrinterContainer& printers)
: pNode_(p)
, width_(0)
, nextPrinters_(printers)
{
assert(pNode_);
UpdateWidth();
}
virtual ~NodePrinter(){}
NodePrinter(const NodePrinter&) = delete;
NodePrinter& operator =(const NodePrinter&) = delete;
public:
void UpdateWidth()
{
width_ = CalcDataWidth_(pNode_->data);
}
virtual void Print() const
{
// 璁$畻宸﹀彸瀛愭爲瀹藉害
size_t leftChildWidth = CalcWidth_(pNode_->pLeftChild);
size_t rightChildWidth = CalcWidth_(pNode_->pRightChild); // +1鏄負浜嗗皢鏁版嵁闅斿紑
// 鎵撳嵃宸﹁竟絀虹櫧
for (size_t i = 0; i < leftChildWidth; ++i)
{
std::cout<<' ';
}
// 鎵撳嵃鑺傜偣
std::cout<<"["<<pNode_->data<<"]";
// 鎵撳嵃鍙寵竟絀虹櫧
for (size_t i = 0; i < rightChildWidth; ++i)
{
std::cout<<' ';
}
// 灝嗗乏鍎垮瓙鏀懼叆涓嬩竴灞傞渶瑕佹墦鍗扮殑鑺傜偣闆嗗悎涓?
if (pNode_->pLeftChild)
{
nextPrinters_.push_back(PSharedPrinter(new NodePrinter(pNode_->pLeftChild, nextPrinters_)));
}
// 灝嗚嚜韜墍鍗犵┖浣嶆斁鍏ヤ笅涓灞傞渶瑕佹墦鍗扮殑鑺傜偣闆嗗悎涓?
nextPrinters_.push_back(PSharedPrinter(new BlankPrinter(width_)));
// 灝嗗彸鍎垮瓙鏀懼叆涓嬩竴灞傞渶瑕佹墦鍗扮殑鑺傜偣闆嗗悎涓?
if (pNode_->pRightChild)
{
nextPrinters_.push_back(PSharedPrinter(new NodePrinter(pNode_->pRightChild, nextPrinters_)));
}
// 灝嗚嚜韜墍鍗犵┖浣嶆斁鍏ヤ笅涓灞傞渶瑕佹墦鍗扮殑鑺傜偣闆嗗悎涓?
nextPrinters_.push_back(PSharedPrinter(new BlankPrinter(width_)));
}
virtual bool IsValid() const{return true;}
};
/// 絀虹櫧鎵撳嵃鑰咃紝涓昏瀹屾垚鎵撳嵃鐖惰妭鐐規墍鍗犵敤鐨勭┖鐧?
class BlankPrinter : public Printer{
size_t count_;
public:
explicit BlankPrinter(size_t c) : count_(c){}
virtual ~BlankPrinter(){}
public:
virtual void Print() const
{
for (size_t i = 0; i < count_; ++i)
{
std::cout<<' ';
}
}
};
/// 騫垮害浼樺厛鎵撳嵃鑺傜偣錛岀洰鍓嶅彧鏀寔鎵撳嵃int鍨嬫暟鎹?
void Print() const
{
std::cerr<<"涓嶆敮鎸佹墦鍗扮殑鏁版嵁綾誨瀷錛?<<typeid(DataType).name()<<"\n";
}
private:
/// 璁$畻鍗佽繘鍒舵暟浣嶆暟
static size_t CalcDataWidth_(int n)
{
assert(false);
}
/**
璁$畻鏍戝搴?
鍥犱負綰﹀畾絀烘爲瀹藉害涓?錛屽彾瀛愬搴︿負1錛屾墍浠ユ爲瀹藉害絳変簬宸﹀彸瀛愭爲瀹藉害鍜?鏁版嵁鎵鍗犵殑浣嶆暟
*/
static size_t CalcWidth_(const Node_* pRoot)
{
if (!pRoot)
{
return 0;
}
return CalcWidth_(pRoot->pLeftChild) + CalcWidth_(pRoot->pRightChild) + CalcDataWidth_(pRoot->data);
}
#endif // _PRINT
public:
/// 鎻掑叆鏁版嵁
void Insert(const DataType& data)
{
#ifdef _PRINT
std::cout<<"鎻掑叆鏁版嵁錛?<<data<<std::endl;
#endif // _PRINT
Insert_(data, pRoot_);
}
/// 鍒犻櫎鏁版嵁
void Erase(const DataType& data)
{
#ifdef _PRINT
std::cout<<"鍒犻櫎鏁版嵁錛?<<data<<std::endl;
#endif // _PRINT
Erase_(data, pRoot_);
}
/// 娓呯┖
void Clear()
{
#ifdef _PRINT
std::cout<<"娓呯┖"<<std::endl;
#endif // _PRINT
// 閿姣佹墍鏈夎妭鐐?
RecursDestroyNode_(pRoot_);
pRoot_ = 0;
}
private:
/// 鍒涘緩鑺傜偣
static Node_* CreateNode_(const DataType& data)
{
return new Node_(data);
}
/// 閿姣佽妭鐐?
static void DestroyNode_(Node_* pNode)
{
delete pNode;
}
/// 閫掑綊閿姣佽妭鐐?
static void RecursDestroyNode_(Node_* pNode)
{
if (pNode)
{
// 鍏堥掑綊閿姣佸瓙鑺傜偣
RecursDestroyNode_(pNode->pLeftChild);
RecursDestroyNode_(pNode->pRightChild);
// 鍐嶉攢姣佽嚜韜?
DestroyNode_(pNode);
}
}
/// 鑾峰彇鏍戦珮搴︼紝綰﹀畾絀烘爲楂樺害涓?1
static int GetHeight_(const Node_* pRoot)
{
return pRoot ? pRoot->height : -1;
}
/**
璁$畻鏍戦珮搴?
鍥犱負綰﹀畾絀烘爲楂樺害涓?1錛屽彾瀛愰珮搴︿負0錛屾墍浠ユ爲楂樺害絳変簬宸﹀彸瀛愭爲杈冮珮鑰呴珮搴?1
*/
static int CalcHeight_(const Node_* pRoot)
{
assert(pRoot); // 鏂█鏍戝瓨鍦?
return std::max(GetHeight_(pRoot->pLeftChild), GetHeight_(pRoot->pRightChild)) + 1;
}
/**
涓庡瓙鏍戣繘琛屽崟鏃嬭漿
鐢變簬鏃嬭漿鍚庤妭鐐瑰皢鎴愪負鍏跺師鍎垮瓙鐨勫効瀛愶紝鏁呰妭鐐規寚閽坧Node灝嗕細鎸囧悜鍏跺師鍎垮瓙
pChild1鎸囧悜琚棆杞殑鍎垮瓙鎴愬憳鎸囬拡錛宲Child2鎸囧悜鍙︿竴涓効瀛愭垚鍛樻寚閽?
*/
static void SingleRatateWithChild_(Node_*& pNode, Node_* Node_::* pChild1, Node_* Node_::* pChild2)
{
assert(pChild1 && pChild2); // 鏂█鎴愬憳鍙橀噺鎸囬拡鏈夋晥
assert(pNode); // 鏂█鑺傜偣瀛樺湪
// 鑺傜偣鐨勫効瀛?閲嶅畾鍚戜簬鍎垮瓙1鐨勫効瀛?
Node_* pOriginalChild = pNode->*pChild1;
pNode->*pChild1 = pOriginalChild->*pChild2;
// 鑺傜偣鐨勫師鍎垮瓙1鐨勫効瀛?閲嶅畾鍚戜簬鑺傜偣
pOriginalChild->*pChild2 = pNode;
// 鏃嬭漿涔嬪悗闇瑕侀噸鏂拌綆楅珮搴?
pNode->height = CalcHeight_(pNode);
pOriginalChild->height = CalcHeight_(pOriginalChild);
// pNode鎸囧悜鍏跺師鍎垮瓙
pNode = pOriginalChild;
}
/// 涓庡乏瀛愭爲榪涜鍗曟棆杞?
static void RotateWithLeftChild_(Node_*& pNode)
{
SingleRatateWithChild_(pNode, &Node_::pLeftChild, &Node_::pRightChild);
}
/// 涓庡彸瀛愭爲榪涜鍗曟棆杞?
static void RotateWithRightChild_(Node_*& pNode)
{
SingleRatateWithChild_(pNode, &Node_::pRightChild, &Node_::pLeftChild);
}
/**
涓庡瓙鏍戣繘琛屽弻鏃嬭漿
鐢變簬鏃嬭漿鍚庤妭鐐瑰皢鎴愪負鍏跺師鍎垮瓙鐨勫効瀛愶紝鏁呰妭鐐規寚閽坧Node灝嗕細鎸囧悜鍏跺師鍎垮瓙
pChild1鎸囧悜琚棆杞殑鍎垮瓙鎴愬憳鎸囬拡錛宲Child2鎸囧悜鍙︿竴涓効瀛愭垚鍛樻寚閽?
*/
static void DoubleRatateWithChild_(Node_*& pNode, Node_* Node_::* pChild1, Node_* Node_::* pChild2)
{
assert(pChild1); // 鏂█鎴愬憳鍙橀噺鎸囬拡鏈夋晥
// 鍏堝鍎垮瓙榪涜涓嬈℃棆杞?
SingleRatateWithChild_(pNode->*pChild1, pChild2, pChild1);
// 鍐嶅鑷繁榪涜涓嬈℃棆杞?
SingleRatateWithChild_(pNode, pChild1, pChild2);
}
/// 涓庡乏瀛愭爲榪涜鍙屾棆杞?
static void DoubleRotateWithLeftChild_(Node_*& pNode)
{
DoubleRatateWithChild_(pNode, &Node_::pLeftChild, &Node_::pRightChild);
}
/// 涓庡彸瀛愭爲榪涜鍙屾棆杞?
static void DoubleRotateWithRightChild_(Node_*& pNode)
{
DoubleRatateWithChild_(pNode, &Node_::pRightChild, &Node_::pLeftChild);
}
/**
紜畾宸﹀瓙鏍戞槸鍚﹁繃楂橈紙鐮村潖浜咥VL騫寵 鏉′歡錛夛紝鏄垯涓庡叾榪涜鏃嬭漿
褰撳湪宸﹀瓙鏍戜腑鎻掑叆鏂拌妭鐐癸紝鎴栬呭湪鍙沖瓙鏍戜腑鍒犻櫎鑺傜偣鏃朵嬌鐢?
*/
static void RatateWithLeftChildIfNeed_(Node_*& pNode)
{
// AVL騫寵 鏉′歡涓哄乏鍙沖瓙鏍戦珮搴︾浉宸笉瓚呰繃1
// 宸﹀瓙鏍戞瘮鍙沖瓙鏍戦珮2錛岄渶瑕侀氳繃鏃嬭漿鏉ヤ嬌涔嬮噸鏂拌揪鍒癆VL騫寵 鏉′歡
if (2 == GetHeight_(pNode->pLeftChild) - GetHeight_(pNode->pRightChild))
{
if (GetHeight_(pNode->pLeftChild->pLeftChild) > GetHeight_(pNode->pLeftChild->pRightChild))
{
// 宸﹀瓙鏍戠殑宸﹀瓙鏍戦珮浜庡乏瀛愭爲鐨勫彸瀛愭爲錛屽簲褰撲笌宸﹀瓙鏍戣繘琛屽崟鏃嬭漿
RotateWithLeftChild_(pNode);
}
else
{
// 宸﹀瓙鏍戠殑鍙沖瓙鏍戦珮浜庡乏瀛愭爲鐨勫乏瀛愭爲錛屽簲褰撲笌宸﹀瓙鏍戣繘琛屽弻鏃嬭漿
DoubleRotateWithLeftChild_(pNode);
}
}
}
/**
紜畾鍙沖瓙鏍戞槸鍚﹁繃楂橈紙鐮村潖浜咥VL騫寵 鏉′歡錛夛紝鏄垯涓庡叾榪涜鏃嬭漿
褰撳湪鍙沖瓙鏍戜腑鎻掑叆鏂拌妭鐐癸紝鎴栬呭湪宸﹀瓙鏍戜腑鍒犻櫎鑺傜偣鏃朵嬌鐢?
*/
static void RatateWithRightChildIfNeed_(Node_*& pNode)
{
// AVL騫寵 鏉′歡涓哄乏鍙沖瓙鏍戦珮搴︾浉宸笉瓚呰繃1
// 鍙沖瓙鏍戞瘮宸﹀瓙鏍戦珮2錛岄渶瑕侀氳繃鏃嬭漿鏉ヤ嬌涔嬮噸鏂拌揪鍒癆VL騫寵 鏉′歡
if (2 == GetHeight_(pNode->pRightChild) - GetHeight_(pNode->pLeftChild))
{
if (GetHeight_(pNode->pRightChild->pRightChild) > GetHeight_(pNode->pRightChild->pLeftChild))
{
// 鍙沖瓙鏍戠殑鍙沖瓙鏍戦珮浜庡彸瀛愭爲鐨勫乏瀛愭爲錛屽簲褰撲笌鍙沖瓙鏍戣繘琛屽崟鏃嬭漿
RotateWithRightChild_(pNode);
}
else
{
// 鍙沖瓙鏍戠殑宸﹀瓙鏍戦珮浜庡彸瀛愭爲鐨勫彸瀛愭爲錛屽簲褰撲笌鍙沖瓙鏍戣繘琛屽弻鏃嬭漿
DoubleRotateWithRightChild_(pNode);
}
}
}
/**
鎻掑叆鏂拌妭鐐癸細
濡傛灉褰撳墠鑺傜偣涓虹┖鍒欒鏄庢壘鍒頒簡鎻掑叆鐨勪綅緗紝鍒涘緩鏂拌妭鐐癸紝榪斿洖鎻掑叆鎴愬姛
濡傛灉鏁版嵁灝忎簬褰撳墠鑺傜偣鏁版嵁鍒欏埌宸﹀瓙鏍戜腑鎻掑叆錛屽鏋滄彃鍏ユ垚鍔燂紝鍙兘闇瑕佹棆杞嬌涔嬮噸鏂板鉤琛★紙宸﹀瓙鏍戣繃楂橈級錛岄噸鏂拌綆楅珮搴?
濡傛灉鏁版嵁澶т簬褰撳墠鑺傜偣鏁版嵁鍒欓亾鍙沖瓙鏍戜腑鎻掑叆錛屽鏋滄彃鍏ユ垚鍔燂紝鍙兘闇瑕佹棆杞嬌涔嬮噸鏂板鉤琛★紙鍙沖瓙鏍戣繃楂橈級錛岄噸鏂拌綆楅珮搴?
濡傛灉鏁版嵁絳変簬褰撳墠鑺傜偣鏁版嵁鍒欎粈涔堥兘涓嶅仛錛岃繑鍥炴彃鍏ュけ璐?
*/
static bool Insert_(const DataType& data, Node_*& pNode)
{
if (!pNode)
{
// 鎵懼埌浣嶇疆錛屽垱寤鴻妭鐐?
pNode = CreateNode_(data);
assert(pNode); // 鏂█鍒涘緩鑺傜偣鎴愬姛
return true;
}
else if (data < pNode->data)
{
// 灝嗚緝灝忕殑鏁版嵁鎻掑叆鍒板乏瀛愭爲
if (Insert_(data, pNode->pLeftChild))
{
// 鎴愬姛鎻掑叆鏂拌妭鐐?
// 濡傛灉闇瑕侊紝鍒欎笌宸﹀瓙鏍戣繘琛屾棆杞互緇存寔AVL騫寵 鏉′歡
RatateWithLeftChildIfNeed_(pNode);
// 閲嶆柊璁$畻楂樺害
pNode->height = CalcHeight_(pNode);
return true;
}
}
else if (data > pNode->data)
{
// 灝嗚緝澶х殑鏁版嵁鎻掑叆鍒板彸瀛愭爲
if (Insert_(data, pNode->pRightChild))
{
// 鎴愬姛鎻掑叆鏂拌妭鐐?
// 濡傛灉闇瑕侊紝鍒欎笌鍙沖瓙鏍戣繘琛屾棆杞互緇存寔AVL騫寵 鏉′歡
RatateWithRightChildIfNeed_(pNode);
// 閲嶆柊璁$畻楂樺害
pNode->height = CalcHeight_(pNode);
return true;
}
}
else
{
// 閲嶅鏁版嵁錛堜粈涔堜篃涓嶅仛錛屾垨鑰呰繘琛岃鏁幫級
}
return false;
}
/**
鍒犻櫎鑺傜偣
鏌ユ壘琚垹闄ょ殑鑺傜偣錛?
濡傛灉褰撳墠鑺傜偣涓虹┖鍒欒鏄庢病鏈夋壘鍒拌鍒犻櫎鐨勮妭鐐癸紝榪斿洖鍒犻櫎澶辮觸
濡傛灉琚垹闄ょ殑鏁版嵁灝忎簬鑺傜偣鏁版嵁錛屽垯鍦ㄨ妭鐐圭殑宸﹀瓙鏍戜腑鏌ユ壘騫跺垹闄わ紝濡傛灉鍒犻櫎鎴愬姛錛屽彲鑳介渶瑕佹棆杞嬌涔嬮噸鏂板鉤琛★紙鍙沖瓙鏍戣繃楂橈級錛岄噸鏂拌綆楅珮搴?
濡傛灉琚垹闄ょ殑鏁版嵁澶т簬鑺傜偣鏁版嵁錛屽垯鍦ㄨ妭鐐圭殑鍙沖瓙鏍戜腑鏌ユ壘騫跺垹闄わ紝濡傛灉鍒犻櫎鎴愬姛錛屽彲鑳介渶瑕佹棆杞嬌涔嬮噸鏂板鉤琛★紙宸﹀瓙鏍戣繃楂橈級錛岄噸鏂拌綆楅珮搴?
濡傛灉琚垹闄ょ殑鏁版嵁絳変簬鑺傜偣鏁版嵁錛屽垯鎵懼埌琚垹闄ょ殑鑺傜偣錛屽紑濮嬪垹闄わ紝榪斿洖鍒犻櫎鎴愬姛
鍒犻櫎鑺傜偣榪囩▼錛屽皢琚垹闄ょ殑鑺傜偣浣滀負鏍囪鑺傜偣錛?
濡傛灉鏍囪鑺傜偣瀛樺湪宸﹀彸鍙屽瓙鏍戯紝鍒╃敤鍙沖瓙鏍戠殑鏈灝忚妭鐐圭殑鏁版嵁鏇挎崲姝よ妭鐐規暟鎹紝鐒跺悗鍒犻櫎鍙沖瓙鏍戠殑鏈灝忚妭鐐癸細
濡傛灉鍙沖瓙鏍戞湁宸﹀瓙鏍戯紝浠庡乏瀛愭爲涓壘鍒版渶灝忚妭鐐癸紝灝嗗叾鍙沖瓙鏍戞彁鍗囦竴綰э紝鍙兘闇瑕佹棆杞嬌鍏剁埗鑺傜偣閲嶆柊騫寵 錛堝叾鐖惰妭鐐圭殑鍙沖瓙鏍戣繃楂橈級錛岄噸鏂拌綆楀叾鐖惰妭鐐歸珮搴?
濡傛灉鍙沖瓙鏍戞病鏈夊乏瀛愭爲錛屾鏃跺彸瀛愭爲鍒欏嵆鏄渶灝忚妭鐐癸紝灝嗗叾鍙沖瓙鏍戞彁鍗囦竴綰?
鍙兘闇瑕佹棆杞嬌鏍囪鑺傜偣閲嶆柊騫寵 錛堟爣璁拌妭鐐圭殑宸﹀瓙鏍戣繃楂橈級錛岄噸鏂拌綆楁爣璁拌妭鐐歸珮搴?
濡傛灉鏍囪鑺傜偣涓嶅瓨鍦ㄥ乏鍙沖弻瀛愭爲錛屽垹闄ゆ爣璁拌妭鐐癸紝鎻愬崌鍏跺瓙鏍?
*/
static bool Erase_(const DataType& data, Node_*& pNode)
{
if (!pNode)
{
// 娌℃湁鎵懼埌鑺傜偣
return false;
}
else if (data < pNode->data)
{
// 鑺傜偣杈冨皬錛屽湪宸﹀瓙鏍戜腑鍒犻櫎
if (Erase_(data, pNode->pLeftChild))
{
// 鎴愬姛鍒犻櫎鑺傜偣
// 濡傛灉闇瑕侊紝鍒欎笌鍙沖瓙鏍戣繘琛屾棆杞互緇存寔AVL騫寵 鏉′歡
RatateWithRightChildIfNeed_(pNode);
// 閲嶆柊璁$畻楂樺害
pNode->height = CalcHeight_(pNode);
return true;
}
}
else if (data > pNode->data)
{
// 鑺傜偣杈冨ぇ錛屽湪鍙沖瓙鏍戜腑鍒犻櫎
if (Erase_(data, pNode->pRightChild))
{
// 鎴愬姛鍒犻櫎鑺傜偣
// 濡傛灉闇瑕侊紝鍒欎笌宸﹀瓙鏍戣繘琛屾棆杞互緇存寔AVL騫寵 鏉′歡
RatateWithLeftChildIfNeed_(pNode);
// 閲嶆柊璁$畻楂樺害
pNode->height = CalcHeight_(pNode);
return true;
}
}
else
{
// 鎵懼埌浜嗛渶瑕佽鍒犻櫎鐨勮妭鐐?
if (pNode->pLeftChild && pNode->pRightChild)
{
// 瀛樺湪鍙屽瓙鏍戯紝鍒╃敤鍙沖瓙鏍戞渶灝忚妭鐐規浛鎹紝騫跺垹闄ゅ彸瀛愭爲鏈灝忚妭鐐?
Node_* pMin = pNode->pRightChild;
if (pNode->pRightChild->pLeftChild)
{
// 鍙沖瓙鏍戝瓨鍦ㄥ乏瀛愭爲錛屼粠鍙沖瓙鏍戠殑宸﹀瓙鏍戜腑鎵炬渶灝忚妭鐐?
Node_* pMinParent = pNode->pRightChild;
while (pMinParent->pLeftChild->pLeftChild)
{
pMinParent = pMinParent->pLeftChild;
}
pMin = pMinParent->pLeftChild;
// 鎻愬崌鏈灝忚妭鐐圭殑鍙沖瓙鏍?
pMinParent->pLeftChild = pMin->pRightChild;
// 濡傛灉闇瑕侊紝鏈灝忚妭鐐圭殑鐖惰妭鐐瑰垯涓庡叾鍙沖瓙鏍戣繘琛屾棆杞互緇存寔AVL騫寵 鏉′歡
RatateWithRightChildIfNeed_(pMinParent);
// 閲嶆柊璁$畻鏈灝忚妭鐐圭殑鐖惰妭鐐圭殑楂樺害
pMinParent->height = CalcHeight_(pMinParent);
}
else
{
// 鍙沖瓙鏍戜笉瀛樺湪宸﹀瓙鏍戯紝閭d箞鎻愬崌鍙沖瓙鏍戠殑鍙沖瓙鏍?
pNode->pRightChild = pNode->pRightChild->pRightChild;
}
// 鐢ㄦ渶灝忚妭鐐規浛鎹?
pNode->data = pMin->data;
// 鍒犻櫎鏈灝忚妭鐐?
DestroyNode_(pMin);
// 濡傛灉闇瑕侊紝鍒欎笌宸﹀瓙鏍戣繘琛屾棆杞互緇存寔AVL騫寵 鏉′歡
RatateWithLeftChildIfNeed_(pNode);
// 閲嶆柊璁$畻楂樺害
pNode->height = CalcHeight_(pNode);
}
else
{
// 涓嶅瓨鍦ㄥ弻瀛愭爲錛屽垯鐩存帴鐢ㄥ効瀛愭浛鎹?
Node_* pTemp = pNode;
pNode = pNode->pLeftChild ? pNode->pLeftChild : pNode->pRightChild;
// 閿姣佽妭鐐?
DestroyNode_(pTemp);
}
return true;
}
return false;
}
}; // class AVLTree
#ifdef _PRINT
template<>
void AVLTree<int>::Print() const
{
if (!pRoot_)
{
return;
}
PrinterContainer nextPrinters; // 涓嬩竴灞傞渶瑕佹墦鍗扮殑瀵硅薄闆嗗悎
nextPrinters.push_back(PSharedPrinter(new NodePrinter(pRoot_, nextPrinters)));
while (nextPrinters.end() != std::find_if(nextPrinters.begin(), nextPrinters.end(), std::mem_fn(&Printer::IsValid)))
{
auto printers(std::move(nextPrinters)); // 褰撳墠闇瑕佹墦鍗扮殑瀵硅薄闆嗗悎
// 鎵撳嵃涓琛?
std::for_each(printers.begin(), printers.end(), std::mem_fn(&Printer::Print));
// 鎹㈣
std::cout<<std::endl;
}
}
template<>
size_t AVLTree<int>::CalcDataWidth_(int n)
{
if (0 == n)
{
return 1+2; // +2鏄負[]絎﹀彿鍗犱綅
}
size_t ret = 2; // 2鏄負[]絎﹀彿鍗犱綅
if (0 > n)
{
// 澶嶆暟錛屾坊鍔犵鍙蜂綅
++ret;
n = -n;
}
while (n)
{
++ret;
n /= 10;
}
return ret;
}
#endif // _PRINT
} // namespace ghost
#endif // AVL_TREE_H
main.cpp鏂囦歡
#define _PRINT
#include "AVLTree.h"
#include <iostream>
#include <ctime>
/// 鎵撳嵃AVL鏍?
template<typename T>
void PrintAVLTree(const ghost::AVLTree<T>& tree)
{
#ifdef _PRINT
std::cout<<"--------------AVLTree--------------"<<std::endl;
tree.Print();
std::cout<<"------------------------------------------"<<std::endl;
#else
std::cerr<<"鏈紑鍚墦鍗伴澶勭悊鍣紝涓嶆彁渚汚VL鏍戠殑鎵撳嵃錛乗n";
#endif // _PRINT
}
static const size_t TEST_DATA_COUNT = 10; // 嫻嬭瘯鏁版嵁鐨勪釜鏁?
static const size_t TEST_DATA_LOWER_LIMIT = 0; // 嫻嬭瘯鏁版嵁鐨勪笅闄?
static const size_t TEST_DATA_UPPER_LIMIT = 10; // 嫻嬭瘯鏁版嵁鐨勪笂闄?
/// 闅忔満鏋勯犳祴璇曟暟鎹?
int BuildTestData()
{
return TEST_DATA_LOWER_LIMIT + rand() % (TEST_DATA_UPPER_LIMIT-TEST_DATA_LOWER_LIMIT);
}
int main()
{
srand((int)time(0));
ghost::AVLTree<int> tree;
// 闅忔満鎻掑叆嫻嬭瘯鏁版嵁
for (size_t i = 0; i < TEST_DATA_COUNT; ++i)
{
tree.Insert(BuildTestData());
PrintAVLTree(tree);
}
// 闅忔満鍒犻櫎嫻嬭瘯鏁版嵁
for (size_t i = 0; i < TEST_DATA_COUNT; ++i)
{
tree.Erase(BuildTestData());
PrintAVLTree(tree);
}
// tree.Insert(5);
// PrintAVLTree(tree);
//
// tree.Insert(2);
// PrintAVLTree(tree);
//
// tree.Insert(8);
// PrintAVLTree(tree);
//
// tree.Insert(1);
// PrintAVLTree(tree);
//
// tree.Insert(4);
// PrintAVLTree(tree);
//
// tree.Insert(7);
// PrintAVLTree(tree);
//
// tree.Insert(3);
// PrintAVLTree(tree);
//
// tree.Insert(6); // 姝ゆ椂搴旇Е鍙戜竴嬈″崟鏃嬭漿
// PrintAVLTree(tree);
return 0;
}
浣滆? Evil.Ghost 鍙戣〃浜?2011-06-17 14:53 鍘熸枃閾炬帴
鏈鏂版柊闂伙細
· 閮彴閾禐娌沖崡宸ヤ漢绱犺川浣?iPhone鐢熶駭钀芥埛閮戝窞(2011-06-17 17:53)
· RIM棣栧腑榪愯惀瀹樼梾浼戠鑱?縐嬪閲嶈繑宸ヤ綔宀椾綅(2011-06-17 17:50)
· 鍦熻眴緗戜笅鍗婂勾璧寸撼鏂揪鍏嬩笂甯?铻嶈祫1.5浜跨編鍏?/a>(2011-06-17 17:48)
· 浼燤cAfee鎬昏灝嗚煩妲借嚦鍒濆垱鍏徃鍑轟換CEO(2011-06-17 17:47)
· 鎼滀漢鍔熻兘姝e紡涓婄嚎 鎼滄悳紺懼尯鍖栨垬鐣ュ啀鍗囩駭(2011-06-17 17:46)
緙栬緫鎺ㄨ崘錛?a target="_blank">鍍忎漢鑴戜竴鏍鋒濊?鎻Kinect宸ヤ綔鍘熺悊
緗戠珯瀵艱埅錛?a target="_blank">鍗氬鍥欏?/a> 鎴戠殑鍥瓙 鏂伴椈 闂瓨 灝忕粍 鍗氶棶 鐭ヨ瘑搴?/a>
榪欐鎴戜滑灝嗚緇橶idget澧炲姞涓浜涚姸鎬侊紝騫朵嬌鍏惰兘澶熸帴鍙楀嚭娑堟伅澶勭悊鎵╁睍錛屾祴璇曞伐紼嬩腑瀹炵幇浜嗕竴涓寜閽殑娑堟伅澶勭悊鎵╁睍銆?/p>
Widget鐘舵侊細
涔嬪墠鐨勬帶浠跺彧鏄粯鍒朵簡涓涓竟妗嗭紝騫朵笖鎬繪槸浼氬湪紿楀彛涓樉紺恒傚疄闄呬笂鎴戜滑寰寰浼氬笇鏈涜兘澶熻鏌愪釜鎺т歡鏄劇ず鎴栬呴殣钘忋佸彲鐢ㄦ垨鑰呬笉鍙敤絳夌瓑錛岄偅涔堟帶浠跺簲璇ュ叿鏈夎兘澶熸爣璇嗚繖浜涚姸鎬佺殑灞炴э紝浜庢槸鎴戜滑緇橶idget澧炲姞浜嗙姸鎬佹蹇點?/p>
// 鐘舵佺浉鍏?/span>
void AddStates(size_t states);
void SubStates(size_t states);
bool CheckState(widget::StateBitField s);
涓婇潰鏄姸鎬佺浉鍏崇殑鍑犱釜鎺ュ彛錛屽寘鎷簡澧炲姞鐘舵佺粍錛屽噺灝戠姸鎬佺粍錛屾嫻嬬姸鎬併傝繖閲屾湁涓姸鎬佺粍鐨勬蹇碉紝鏄洜涓烘垜灝嗙姸鎬佺敤浣嶅煙鏉ュ疄鐜幫紝閭d箞浠栦滑灝卞彲浠ラ氳繃or榪愮畻鏉ュ緱鍒板涓姸鎬佺殑闆嗗悎錛屾垜灝辮繖涓泦鍚堢О涓虹姸鎬佺粍銆?/p>
enum StateBitField{
STATE_VISIBLE = 1 << 0, // 鎺т歡鍙錛熷喅瀹氭帶浠舵槸鍚﹁緇樺埗
STATE_ENABLE = 1 << 1, // 鎺т歡鍙敤錛熷喅瀹氭帶浠舵槸鍚﹀搷搴旈紶鏍囬敭鐩樻秷鎭?/span>
STATE_TRANSPARENT = 1 << 2, // 鎺т歡閫忔槑錛熷喅瀹氭帶浠舵槸鍚﹀搷搴旈紶鏍囬敭鐩樻秷鎭互鍙婃槸鍚︽樉紺簍ooltip
};
鐩墠鎴戠粰Widget瀹氫箟浜?涓姸鎬侊細鍙銆佸彲鐢ㄣ侀忔槑銆傞粯璁ゅ垱寤虹殑Widget鏄笉鍙銆佷笉鍙敤銆佷笉閫忔槑鐨勶紝闇瑕佸湪鍒涘緩鎴愬姛鍚庢墜鍔ㄨ緗紝渚嬪錛?/p>
// 寤虹珛鏍規帶浠?/span>
auto pRootWidget = ghost::Widget::Create();
pRootWidget->AddStates(銆銆ghost::widget::STATE_VISIBLE|ghost::widget::STATE_ENABLE|ghost::widget::STATE_TRANSPARENT);
娑堟伅澶勭悊鎵╁睍錛?/strong>
閫氬父瀵逛簬鎺т歡鏉ヨ錛屾病鏈夋秷鎭鐞嗗氨絳変簬娌℃湁鐢熷懡鎰忎箟錛岄偅涔堜負Widget娣誨姞娑堟伅澶勭悊鎵╁睍灝辨剰鍛崇潃浣縒idget媧昏搗鏉ワ紝榪欐鎴戜滑灝辨潵瀹屾垚榪欎釜浠誨姟錛屾湡寰匴idget媧昏搗鏉ョ殑閭f縺鍔ㄤ漢蹇冪殑涓鍒匯傚拰浠ュ線娣誨姞鎵╁睍鏀寔涓鏍鳳紝涓烘墿灞曠紪鍐欎竴涓娊璞″熀綾伙紝鍦╓idget鐨勫叧鑱斿璞$鐞嗕腑娣誨姞榪欎釜鎵╁睍鐨勫叧鑱斿鐞嗭紝鐒跺悗鍦╓idget鐨凷endMessage澶勭悊閫昏緫閲屽鍔犲娑堟伅澶勭悊鎵╁睍鐨勬敮鎸併傞偅涔堟垜浠殑SendMessage瀹炵幇灝卞彉鎴愪簡榪欐牱錛?/p>
int Widget::SendMessage(widget::Message message, void* param1/* = 0*/, void* param2/* = 0*/)
{
if (!CheckState(widget::STATE_ENABLE))
{
// 涓嶅搷搴旈紶鏍囬敭鐩樻秷鎭?/span>
if ((widget::MSG_MOUSE_FIRST <= message
&& widget::MSG_MOUSE_LAST >= message)
||(widget::MSG_KEY_FIRST <= message
&& widget::MSG_KEY_LAST >= message))
{
return widget::MSG_RESULT_NONE;
}
}
if (CheckState(widget::STATE_TRANSPARENT))
{
// 涓嶅搷搴旈紶鏍囬敭鐩樻秷鎭紝涓嶆樉紺簍ooltip
if ((widget::MSG_MOUSE_FIRST <= message
&& widget::MSG_MOUSE_LAST >= message)
||(widget::MSG_KEY_FIRST <= message
&& widget::MSG_KEY_LAST >= message))
{
return widget::MSG_RESULT_NONE;
}
}
auto pRelatedObject = GetRelatedObject();
if (pRelatedObject)
{
auto pMessageHandle = pRelatedObject->GetMessageHandle();
if (pMessageHandle)
{
bool handled = false;
int res = pMessageHandle->OnMessage(this, message, param1, param2, handled);
if (handled)
{
return res;
}
}
}
switch (message)
{
#ifdef _DEBUG
case widget::MSG_DRAW:
{
HBRUSH hBrush = ::CreateSolidBrush(pImpl_->testFrameColor_);
::FrameRect((HDC)param1, &pImpl_->absoluteRect_, hBrush);
::DeleteObject(hBrush);
}
break;
#endif // _DEBUG
case widget::MSG_HIT_TEST:
if (::PtInRect(&pImpl_->absoluteRect_, *(const POINT*)param1))
{
return ~widget::MSG_RESULT_NONE;
}
break;
}
return widget::MSG_RESULT_NONE;
}
鎴戝嬈℃彁鍒頒簡tooltip錛屼絾鏄垜浠繖嬈″茍娌℃湁涓篧idget澧炲姞鍏舵敮鎸侊紝瀹冨皢鍦ㄥ悗闈㈣鍔犲叆鍒癢idget涓潵銆傚彲浠ョ湅鍒拌繖閲屽鐞嗘湁瀵規秷鎭鐞嗘墿灞曠殑鏀寔錛岃繕鏈夌姸鎬佸浜庢秷鎭殑褰卞搷銆傝繖閲屽嚭鐜頒簡涓涓狹SG_HIT_TEST錛岃繖鏄竴涓柊澧炵殑娑堟伅銆傝繖嬈′負Widget娣誨姞浜嗗緢澶氱殑娑堟伅錛屽寘鎷簡榧犳爣銆侀敭鐩樼瓑錛岃灝嗛紶鏍囨秷鎭噯紜殑鍙戦佺粰姝g‘鐨勬帶浠訛紝閭d箞鐐瑰嚮嫻嬭瘯鏄繀涓嶅彲灝戠殑錛岃繖涓狹SG_HIT_TEST娑堟伅鍒欐槸鐢ㄤ簬鎺т歡澶勭悊鐐瑰嚮嫻嬭瘯鐨勩?/p>
鐐瑰嚮嫻嬭瘯錛?/strong>
褰撳鍣ㄤ駭鐢熶簡榧犳爣浜嬩歡鐨勬椂鍊欙紝鎴戜滑鑳藉寰楀埌榧犳爣鐑偣鍦ㄥ鍣ㄤ腑鐨勫潗鏍囥傚墠闈㈡垜涔熷嬈℃彁鍒幫紝妯℃嫙鎺т歡鏄鍣ㄤ腑鐨勬煇涓尯鍩燂紝閭d箞褰撻紶鏍囩儹鐐逛綅浜庢煇涓帶浠舵墍澶勭殑鍖哄煙鐨勬椂鍊欙紝閭d箞榪欎釜榧犳爣浜嬩歡鎴戜滑灝卞簲褰撲氦鐢辮繖涓帶浠惰繘琛屽鐞嗭紙榪欐槸閫氬父鎯呭喌錛屼篃鏈夊彲鑳芥煇涓帶浠朵綔涓洪忔槑鎺т歡錛屼笉鎺ュ彈浠諱綍鐐瑰嚮嫻嬭瘯錛夈備簬鏄垜浠究閫氳繃鐐瑰嚮嫻嬭瘯錛圚itTest錛夎繖涓闂帴鍙f潵鎵懼埌搴旇澶勭悊榧犳爣浜嬩歡鐨勬帶浠躲傚湪鎵懼埌鎺т歡涔嬪悗錛屾垜浠繕灝嗗潗鏍囨槧灝勫埌浜嗘帶浠剁殑鐩稿鍧愭爣緋伙紝榪欐牱鎺т歡灝卞彲浠ヤ互鑷韓鐨勭浉瀵逛綅緗潵澶勭悊榧犳爣浜嬩歡浜嗐?/p>
褰撶劧錛岃繖嬈$殑鍐呭闈炲父澶氾紝鍖呮嫭鍧愭爣鏄犲皠銆佸尯鍩熸槧灝勶紝鎹曡幏榧犳爣鐨勬帶浠躲佹椿鍔ㄦ帶浠躲佺劍鐐規帶浠剁瓑姒傚康閮芥湭鎻愬埌錛屼絾鍦ㄤ唬鐮佷腑榪樻槸鑳藉鐪嬪埌榪欎簺姒傚康鐨勩傚鏋滀竴涓浠嬬粛錛岄偅鏂囩珷灝變細闈炲父鍐楅暱錛屼篃浼氫嬌Widget瀹炵幇榪涘睍緙撴參錛屽洜姝ゆ垜閫氬父閮戒細鐪佺暐涓浜涘唴瀹癸紝榪欎簺鍐呭涔熷氨鍙兘閫氳繃浠g爜闃呰鏉ュ緱鍒頒簡銆?/p>
鎸夐挳錛?/strong>
涓轟簡嫻嬭瘯鎴戜滑榪欐瀹炵幇鐨勫唴瀹癸紝鎴戜滑緙栧啓浜嗕竴涓寜閽殑娑堟伅澶勭悊鎵╁睍銆傜畝鍗曡搗瑙侊紝鎴戜滑浣垮叾涓嶄駭鐢熷懡浠ゃ佷笉緇樺埗鏂囨湰錛屼粎浠呭彧鏄睍紺哄榧犳爣娑堟伅鐨勫鐞嗗拰鐘舵佺殑鍙樺寲鑰屽凡銆?/p>
锘匡豢锘?img src="http://pic002.cnblogs.com/images/2011/95718/2011042410321772.png">
鎴戜滑灝嗗師鍏堟祴璇曚唬鐮佷腑鐨勪腑闂撮偅涓帶浠跺叧鑱斾簡鎸夐挳鐨勬秷鎭鐞嗭紝閭d箞瀹冨氨縐頒負浜嗕竴涓寜閽帶浠朵簡銆傛垜浠彲浠ュ皢榧犳爣縐誨埌瀹冧笂闈㈢偣鍑葷湅鐪嬩細鍙戠敓浠涔堛?/p>
涓嬭澆嫻嬭瘯宸ョ▼浠g爜 鍥犱負鎴戜竴鐩撮兘鍦ㄤ嬌鐢╒C10鏉ョ紪鍐橶idget錛屼篃鐢ㄥ埌浜嗕竴浜涙柊鐨勭壒鎬э紝鎵浠ュ瓙鍟婅繖嬈$殑嫻嬭瘯宸ョ▼鎴戠敓鎴愪簡涓浠絩elease涓嬬殑紼嬪簭錛屾病鏈塚C10鐨勪漢鑷沖皯鑳藉鐪嬪埌鍏惰繍琛屾晥鏋溿?/p>
浣滆? Evil.Ghost 鍙戣〃浜?2011-04-24 10:48 鍘熸枃閾炬帴
鏈鏂版柊闂伙細
· 浜轟漢璧寸編涓婂競錛氭棤濂堝ぇ鏉傜儵 鎸熻祫鏈闃礔acebook(2011-04-24 11:07)
· 浣嶇疆闅愮浜嬩歡榪涘睍錛欸oogle 鍥炲簲錛屽崕灝旇鏃ユ姤璐ㄧ枒(2011-04-24 10:19)
· 娑堟伅縐拌嫻鏋滄嫻嬭瘯T-Mobile鐗坕Phone(2011-04-24 10:04)
· 鎶ュ憡縐?020騫村叏鐞冧簯璁$畻瑙勬ā杈?410浜跨編鍏?/a>(2011-04-24 10:03)
· 娌冨皵鐜涘湪緹庡浗鍔犲窞嫻嬭瘯鍦ㄧ嚎鍟嗗搧閰嶉佹湇鍔?/a>(2011-04-24 09:40)
緙栬緫鎺ㄨ崘錛?a target="_blank">鍗楁柟閮藉競鎶ワ細緗戠粶姝e湪鏀瑰啓鎴戜滑鐨勬濈淮錛?/a>
緗戠珯瀵艱埅錛?a target="_blank">鍗氬鍥欏?/a> 鎴戠殑鍥瓙 鏂伴椈 闂瓨 灝忕粍 鍗氶棶 鐭ヨ瘑搴?/a>
妯℃嫙鎺т歡宸茬粡鍑轟簡闆忓艦錛屾槸搴旇閲嶆瀯涓涓嬩簡銆?/p>
鏂版蹇碉細
鍏跺疄璇存槸鏂版蹇典篃涓嶅敖鐒訛紝鍙槸鍦ㄨ繖鍑犳鐨勫疄鐜頒腑鍙互鍙戠幇錛岃繖涓ā鎷熸帶浠舵鏋朵腑鏈変袱涓ぇ鐨勬蹇碉細瀹瑰櫒鍜屾帶浠躲傛垜浠竴鐩翠竴鏉ラ兘璇寸殑鏄鍣ㄧ獥鍙o紝浣嗘槸鍏跺疄榪欐槸涓彲浠ヤ笂鍗囩殑姒傚康銆傚鍣ㄥ綰充竴涓帶浠朵綋緋伙紝涔熷氨鏄叧鑱斾竴涓牴鎺т歡錛岄偅涔堝畠灝辨湁鐐圭被浼間簬鎴戜滑鐨勬牴鎺т歡浜嗐備絾鏄鍣ㄧ敱蹇呴』瀹炵幇鍜屽叿浣撶獥鍙e拰鎺т歡鐨勪氦浜掞紝鎵浠ユ垜浠笉鑳界畝鍗曠殑灝嗘牴鎺т歡浣滀負瀹瑰櫒銆傚茍涓斿浜庢煇浜涚壒孌婄殑瀹炵幇錛屾垜浠繕鍙兘闇瑕佸瀹瑰櫒鐨勬煇浜涘姛鑳藉姞浠ユ墿灞曪紝鎵浠ユ垜浠繖嬈¢噸鏋勪負瀹瑰櫒鎶借薄浜嗕竴涓熀綾伙紝騫跺疄鐜頒簡涓涓獥鍙e鍣ㄣ?/p>
class Container : public Monopolistic{
using Monopolistic::pWidget_;
using Monopolistic::GetWidget;
public:
Container();
virtual ~Container();
public:
Widget* GetRootWidget() const{return GetWidget();}
public:
virtual bool IsValid() const = 0;
public:
virtual void Invalidate(const RECT& rect){} // 鏃犳晥鍖栧鍣ㄧ煩褰㈠尯鍩?/span>
virtual void Invalidate(HRGN hRgn){} // 鏃犳晥鍖栧鍣ㄤ笉瑙勫垯鍖哄煙
virtual void Invalidate(){} // 鏃犳晥鍖栨暣涓鍣ㄥ尯鍩?/span>
};
瑙h︼細
鍒扮洰鍓嶄負姝紝鎴戜滑鐨勫鍣ㄩ┍鍔ㄥ拰鎺т歡涔嬮棿鍏鋒湁鍗佸垎绱у瘑鐨勮﹀悎鍏崇郴錛堢敓鍛藉懆鏈熻﹀悎錛夛紝榪欐閲嶆瀯鎵撶畻灝嗘瑙h︼紝浣垮緱鎴戜滑鐨勫鍣ㄥ垱寤哄拰鎺т歡浣撶郴鍒涘緩浜掍笉鐩稿叧錛屼粎浠呴氳繃涓嬈℃搷浣滄潵浣垮緱浠栦滑鍏寵仈鎴栬呰В闄ゅ叧鑱斻?/p>
// 寤虹珛紿楀彛瀹瑰櫒
ghost::widget::WindowContainer container;
container.AttachWindow(hWnd);
// 寤虹珛鏍規帶浠?/span>
auto pRootWidget = ghost::Widget::Create();
// 鍏寵仈瀹瑰櫒
pRootWidget->CreateRelationship(&container);
鍑忓皯綾伙細
榪欐榪樻湁涓涓ぇ鐨勫彉鍖栧氨鏄皢鍘熷厛鐨勪竴浜涙蹇佃瀺鍚堟垚浜嗘柊鐨勬蹇碉細椹卞姩銆佹秷鎭繃婊ゃ佹秷鎭槧灝勯兘铻嶅悎鍒頒簡瀹瑰櫒褰撲腑錛屽洜涓鴻繖涓変釜姒傚康鍜屽叿浣撳鍣ㄥ叧緋葷揣瀵嗭紝鎵浠ュ皢浠栦滑榪涜铻嶅悎浠ュ噺灝戞垜浠殑綾繪暟鐩?/p>
鏀惰幏錛?/strong>
榪欐閲嶆瀯寤虹珛浜嗗鍣ㄨ繖涓蹇墊垜浠槸鏈変竴瀹氭敹鑾風殑錛氬師鍏堟垜浠棤娉曡闂帶浠舵墍鍏寵仈鐨勫鍣紝鐜板湪鍙互浜嗐傚師鍏堟帶浠剁殑瀹瑰櫒瀹炵幇涓嶆槗鎵╁睍錛岀幇鍦ㄥ彲浠ラ氳繃緇ф壙鏉ユ墿灞曪紙渚嬪layered紿楀彛錛夛紝鐢氳嚦鍙互涓哄鍣ㄥ疄鐜扮壒鏈夌殑緇樺埗鏈哄埗錛堜緥濡備嬌鐢╫pengl錛屼互鍚庢垜浠娊璞′簡緇樺埗姒傚康渚垮彲浠ョ湅鍒幫紝鐩墠榪樺彧鑳戒嬌鐢℅DI錛夈?/p>
榪欐娌℃湁浠涔堟柊鐨勫唴瀹規坊鍔狅紝浣嗛噸鏋勮繕鏄湁蹇呰鐨勶紝鍛ㄦ湡鎬ч噸鏋勫埄浜庢垜浠鏁翠釜妗嗘灦鐨勭鐞嗭紝鍦ㄩ噸鏋勮繃紼嬩腑杈冨鏄撳彂鐜板拰淇敼BUG銆?/p>
浣滆? Evil.Ghost 鍙戣〃浜?2011-04-19 20:06 鍘熸枃閾炬帴
鏈鏂版柊闂伙細
· 婊″駭緗戠偖杞板垎浼楀搫鎶箍鍛婁環錛氭睙鍗楁槬鎵胯灝嗚皟鏌?/a>(2011-04-20 18:08)
· 鍛ㄩ縛紲庯細鎶鏈瑕?鍟嗕笟棰犺璁?60棰犺浜嗚涓?/a>(2011-04-20 18:03)
· XJP錛氱綉璐喎闈欐湡鎭愭垚涓綰哥┖鏂?/a>(2011-04-20 18:00)
· 浠繪闈烇細涓娉?涓ゅ埗 涓夊鏁?/a>(2011-04-20 17:24)
· 寰蔣錛欳hrome鍜孫pera瀛樺湪HTML5鎵ц婕忔礊(2011-04-20 17:20)
緙栬緫鎺ㄨ崘錛?a target="_blank">鍐嶈皥“鎴戞槸鎬庝箞鎷涜仒紼嬪簭鍛樼殑”
緗戠珯瀵艱埅錛?a target="_blank">鍗氬鍥欏?/a> 鎴戠殑鍥瓙 鏂伴椈 闂瓨 灝忕粍 鍗氶棶 鐭ヨ瘑搴?/a>
鍙墿灞曪細
瑕佷嬌寰楁垜浠殑鎺т歡鍏峰涓瀹氱殑鍙墿灞曟э紝閭d箞蹇呭畾浼氫駭鐢熸帶浠朵箣澶栫殑瀵硅薄浣滀負鎵╁睍錛屽茍涓旇繖涓璞″浜庢帶浠舵潵璇存槸鍙彃鍏ュ彲縐婚櫎鐨勩傜敤浜庢墿灞曠殑瀵硅薄鍜屾帶浠朵箣闂村簲璇ュ叿澶囦竴瀹氱殑鍏崇郴錛屼緥濡傦細1-1錛?-n錛宯-n絳夈傛垜浠皢榪欐牱鐨勫璞″叧緋繪娊璞′簡鍑烘潵錛岀О涔嬩負瀵硅薄鍏崇郴銆?/p>
瀵硅薄鍏崇郴錛?/strong>
涓涓璞″彲鑳藉厑璁稿崟涓璞″鍏惰繘琛屽叧鑱旓紝涔熷彲鑳藉厑璁稿涓璞″鍏惰繘琛屽叧鑱旓紝鐢氳嚦鍙兘鍗沖厑璁稿涓璞¤繘琛屽叧鑱旓紝浣嗗嵈瀵規煇浜涚被鍨嬬殑瀵硅薄闄愬埗涓哄彧鑳藉崟涓殑瀵瑰叾榪涜鍏寵仈銆傛垜浠皢榪欎簺瀵硅薄鎶借薄涓猴細鍗曞璞″叧緋伙紝 澶氬璞″叧緋伙紝鐙崰寮忓璞″叧緋伙紙榪欐槸瀵瑰瀵硅薄鍏崇郴鐨勪竴縐嶆墿灞曪級銆?/p>

class ObjectRelationship{
protected:
ObjectRelationship(){}
public:
virtual ~ObjectRelationship(){}
private:
ObjectRelationship(const ObjectRelationship&);
ObjectRelationship& operator =(const ObjectRelationship&);
public:
bool CreateRelationship(ObjectRelationship* pObject)
{
if (!DoCreateRelationship_(pObject))
{
return false;
}
RelationshipCreated_(pObject);
return true;
}
bool DestroyRelationship(ObjectRelationship* pObject)
{
if (!DoDestroyRelationship_(pObject))
{
return false;
}
RelationshipDestroyed_(pObject);
return true;
}
protected:
virtual bool DoCreateRelationship_(ObjectRelationship* /*pObject*/) = 0;
virtual bool DoDestroyRelationship_(ObjectRelationship* /*pObject*/) = 0;
protected:
virtual void RelationshipCreated_(ObjectRelationship* /*pObject*/){}
virtual void RelationshipDestroyed_(ObjectRelationship* /*pObject*/){}
};
榪欐槸瀵硅薄鍏崇郴鍩虹被錛屾帴鍙e彧鏈変袱涓細寤虹珛鍏崇郴錛岄攢姣佸叧緋匯?/p>
鍗曞璞″叧緋伙紝 澶氬璞″叧緋婚兘媧劇敓浜庤繖涓熀綾伙紝鑰岀嫭鍗犲紡瀵硅薄鍏崇郴鏄疄鐜扮殑涓や釜甯姪鍑芥暟鏉ヨ緟鍔╁瀵硅薄鍏崇郴銆傛垜浠殑Widget媧劇敓浜庡瀵硅薄鍏崇郴錛屽畠渚垮叿澶囦簡鍜屽涓璞″緩绔嬪叧緋葷殑鑳藉姏錛堟垜浠皢鏈変笉鍚岀殑鎵╁睍鍏寵仈鍒癢idget錛夈備負浜嗕究浜庣鐞嗗拰鎵╁睍錛屾垜浠皢鎵鏈夊拰Widget鍏寵仈鐨勬墿灞曟斁鍒頒竴涓璞″綋涓繘琛岀鐞嗭紝Widget鍜屾墿灞曚箣闂寸殑鍏崇郴寤虹珛鍜岄攢姣侀兘濮旀墭榪欎釜瀵硅薄鏉ヨ繘琛屻?/p>
class LayoutChildren;
typedef std::set<LayoutChildren*> LayoutChildrenSet;
class RelatedObject{
Widget* pWidget_; // 鎺т歡
// 鎺т歡鎵鍏寵仈鐨勫璞?/span>
LayoutChildrenSet layoutChildrens_; // 鍙互鏈夊涓竷灞綆$悊綆$悊涓嶅悓鐨勫瓙鎺т歡甯冨眬
private:
friend class Widget;
explicit RelatedObject(Widget* const pWidget);
public: // 鑾峰彇鍏寵仈瀵硅薄鐨勬帴鍙?/span>
const LayoutChildrenSet& GetLayoutChildrens() const{return layoutChildrens_;}
private:
void RelationshipCreated_(ObjectRelationship* pObject);
void RelationshipDestroyed_(ObjectRelationship* pObject);
};
void Widget::RelationshipCreated_(ObjectRelationship* pObject)
{
GetRelatedObject()->RelationshipCreated_(pObject);
}
void Widget::RelationshipDestroyed_(ObjectRelationship* pObject)
{
GetRelatedObject()->RelationshipDestroyed_(pObject);
}
甯冨眬瀛愭帶浠訛細
鎴戜滑涓篧idgt娣誨姞浜嗕竴涓竷灞瀛愭帶浠剁殑鎺ュ彛錛屽綋鎺т歡鑷韓鍖哄煙鍙樺寲鐨勬椂鍊欎細鑷姩鐨勮皟鐢ㄨ繖涓帴鍙o紝褰撶劧鐢ㄦ埛涔熷彲浠ラ殢鏃惰皟鐢ㄦ鎺ュ彛瀵瑰瓙鎺т歡榪涜甯冨眬銆傛鎺ュ彛璐熻矗灝嗘搷浣滀紶閫掔粰鎵╁睍錛屾垜浠冭檻鍒板瓙鎺т歡鐨勫竷灞絳栫暐鍙兘浼氬悇鏈変笉鍚岋紝鍥犳鎴戜滑鑳藉鍏寵仈澶氫釜甯冨眬瀛愭帶浠舵墿灞曞埌Widget錛岃繖浣垮緱鎴戜滑鑳藉浠ヤ笉鍚岀殑甯冨眬絳栫暐鏉ュ尯鍒寰呬笉鍚岀殑瀛愭帶浠躲?/p>
void Widget::LayoutChildren()
{
auto pRelatedObject = GetRelatedObject();
if (pRelatedObject)
{
const widget::LayoutChildrenSet& layoutChildrens = pRelatedObject->GetLayoutChildrens();
std::for_each(
layoutChildrens.begin(), layoutChildrens.end(),
std::bind(std::mem_fn(&widget::LayoutChildren::Layout), std::placeholders::_1, this));
}
}
鎴戜滑鍒涘緩浜嗕竴涓竟緙樺紡甯冨眬鑷帶浠舵墿灞曡繘琛屾祴璇曪紝嫻嬭瘯鏁堟灉鍦ㄦ祴璇曞伐紼嬩腑鑳藉鐪嬪埌銆?/p>
浣滆? Evil.Ghost 鍙戣〃浜?2011-04-12 21:17 鍘熸枃閾炬帴
鏈鏂版柊闂伙細
· 娑堟伅縐癷Pad 3浠嶄笉閲囩敤Retina灞忓箷(2011-04-12 20:29)
· nginx 1.0.0鍙戝竷(2011-04-12 20:27)
· 2011Mozilla寮鍙戣呭ぇ浼氫寒鐐規姠鍏堢湅(2011-04-12 20:24)
· 浜氶┈閫婃垚璋鋒瓕絎竴澶у箍鍛婁富 姣忓勾2浜跨編鍏冿紙鍥撅級(2011-04-12 20:16)
· 涔濆煄OpenFeint涓浗棣栫錛氫笌鑱旈氭帹鎵嬫父(2011-04-12 20:13)
緙栬緫鎺ㄨ崘錛?a target="_blank">浣撻獙Managed Extensibility Framework綺懼鐨勮璁?/a>
緗戠珯瀵艱埅錛?a target="_blank">鍗氬鍥欏?/a> 鎴戠殑鍥瓙 鏂伴椈 闂瓨 灝忕粍 鍗氶棶 鐭ヨ瘑搴?/a>
鎺т歡鏍?/strong>
涓姝ヤ竴姝ュ疄鐜拌嚜宸辯殑妯℃嫙鎺т歡錛?錛?/a>涓殑鍥句笂鎴戜滑鍙互鐪嬪埌錛屾垜浠殑鎺т歡浣撶郴鍏跺疄灝辨槸涓涓帶浠舵爲銆傛瘡涓涓獥鍙e叧鑱斾竴涓牴鎺т歡錛屾墍鏈夋帶浠墮兘鍦ㄨ繖涓牴鎺т歡涔嬩笅錛岀埗鎺т歡鍖呭騫剁鐞嗗瓙鎺т歡錛岄偅涔堟垜浠殑Widget灝卞簲璇ユ槸涓涓爲緇撶偣銆備竴涓爲緇撶偣鑷沖皯鏈夊Parent鍜孋hilren鐨勮緗拰璁塊棶鎺ュ彛錛?/p>
鍦ㄧ埗鎺т歡閿姣佺殑鏃跺欏畠瑕佽礋璐i攢姣佸叾涓嬫墍鏈夌殑瀛愭帶浠訛紙綾諱技紿楀彛閿姣佷篃浼氶攢姣佸叾瀛愮獥鍙o級錛?/p>
瀹炵幇涓垜浠嬌鐢╯td::set鏉ヤ繚瀛樺瓙鎺т歡錛岃繖鏍蜂究浜庨槻姝㈠瓙鎺т歡閲嶅璁劇疆錛屼篃渚夸簬縐婚櫎瀛愭帶浠訛紝緙虹偣灝辨槸涓嶈兘瀵瑰瓙鎺т歡榪涜鎺掑簭銆傚鏋滀互鍚庢垜浠彁渚涙帶浠剁殑z-order姒傚康錛岄偅涔堟垜浠氨浼氫嬌鐢ㄨ兘澶熻繘琛屾帓搴忕殑瀹瑰櫒鏉ュ綰沖瓙鎺т歡銆?/p>
鎺т歡鍖哄煙錛?/strong> windows涓嬶紝鎴戜滑浣跨敤RECT緇撴瀯鏉ヤ繚瀛樻帶浠惰嚜韜浉瀵逛簬紿楀彛瀹㈡埛鍖虹殑鍖哄煙錛岄偅涔堢獥鍙e鎴峰尯灝哄鏀瑰彉鏃朵篃灝辨槸鎴戜滑鎺т歡榪涜甯冨眬鐨勬椂鏈猴紝閭f垜浠氨瑕佸湪娑堟伅榪囨護涓鐞哤M_SIZE娑堟伅浜嗐?/p>
鎴戜滑灝嗘帶浠剁殑甯冨眬浜ょ敱鐖舵帶浠剁鐞嗭紝涔熷氨鏄鎴戜滑鍙渶瑕佹洿鏂版牴鎺т歡鍖哄煙渚垮彲銆傛牴鎺т歡璐熻矗瀵瑰叾瀛愭帶浠惰繘琛屽竷灞錛屽姝ら掑綊銆?/p>
鎺т歡鏇存柊錛?/strong> 褰撴帶浠跺尯鍩熸敼鍙樹簡錛岄偅涔堢浉搴旂殑鍏舵樉紺轟篃搴旂浉搴旂殑榪涜鏇存柊錛屾墍浠ユ垜浠殑SetAbsoluteRect鎺ュ彛鏈変竴涓猽pdate鍙傛暟鐢ㄤ簬鎺у埗鏄惁璁╃獥鍙d駭鐢熸棤鏁堝尯鍩熸縺媧葷粯鍒躲?/p>
鏃㈢劧鎻愬埌浜嗙粯鍒訛紝閭d箞鎴戜滑涔熷簲璇ヨ鎴戜滑鐨勬帶浠跺睍紺哄湪紿楀彛涓婁簡銆?/p>
鎺т歡緇樺埗錛?/strong> 閫氬父鎴戜滑鐨勭獥鍙g▼搴忛兘鏄湪WM_PAINT娑堟伅涓繘琛岀粯鍒訛紝鎴戜滑鐨勬帶浠剁郴緇熷綋鐒朵篃闇瑕佸鐞嗘娑堟伅銆?/p>
榪欓噷寮曞叆浜嗕竴涓緟鍔╁璞″府鍔╂垜浠駭鐢熷唴瀛楧C錛屼紭鍖栨垜浠殑緇樺埗鏁堢巼銆傛垜浠洿鎺eturn浜嗚繖涓秷鎭紝涔熷氨鏄鎴戜滑灝嗚繖涓秷鎭繃婊ゆ帀浜嗐傚墠闈M_SIZE鍜學M_DESTROY鎴戜滑閮芥病鏈夎繃婊わ紝鍙槸鍦ㄨ繖涓椂鏈哄鎺т歡榪涜浜嗛氱煡鎴栬呮搷浣溿備箣鎵浠ヨ榪囨護WM_PAINT娑堟伅鏄洜涓哄閮ㄧ殑緇樺埗鍜屾帶浠剁殑緇樺埗闅句互鍗忚皟錛岄偅涔堟垜浠共鑴嗗氨鎺ョ浜嗙獥鍙e鎴峰尯鐨勭粯鍒朵簡銆?/p>
褰撶劧錛屾帶浠朵篃闇瑕佽礋璐g粯鍒跺叾瀛愭帶浠訛紝閭d箞Draw鎺ュ彛涓究浼氳皟鐢ㄥ瓙鎺т歡鐨凞raw錛屽姝ら掑綊浣垮緱姣忎釜鎺т歡閮借兘澶熷緱浠ョ粯鍒躲?/p>
棣栨鐩磋鐨勭湅鍒版垜浠殑鎺т歡錛?/strong> 鎴戜滑鍦ㄨ皟璇曠増鏈腑錛屼負姣忎釜鎺т歡鐢熸垚浜嗕竴涓殢鏈虹殑棰滆壊錛屾牴鎹帶浠剁殑鍖哄煙緇樺埗浜嗗叾杈規錛岃繖鏍鋒垜浠氨絎竴嬈$洿瑙傜殑鍦ㄧ獥鍙d腑鐪嬪埌浜嗘垜浠殑鎺т歡銆?/p>
锘?img src="http://pic002.cnblogs.com/images/2011/95718/2011040918550120.png"> 榪笉鍙婂緟錛屽叿鏈変簡鍖哄煙鐨勬帶浠訛紝鎴戜滑宸茬粡鎬ュ垏鐨勬兂瑕佸鍏跺竷灞榪涜鎺у埗錛岀粯鍒惰繘琛屽畾鍒朵簡銆傚竷灞鎺у埗鍜岀粯鍒跺畾鍒跺綋鐒跺睘浜庢墿灞曢儴鍒嗭紝閭d箞涓嬮潰灝卞皢瑕佸紩鍏ユ垜浠殑鎵╁睍浣撶郴浜嗭紝灝借鏈熷緟銆?/p>
浣滆? Evil.Ghost 鍙戣〃浜?2011-04-09 19:05 鍘熸枃閾炬帴 鏈鏂版柊闂伙細 緙栬緫鎺ㄨ崘錛?a target="_blank">闈炴垬涔嬬姜錛屼粠姘鎬腑Office璋堣搗
Widget* GetParent() const;
bool InsertChild(Widget* const pChild);
bool RemoveChild(Widget* const pChild);
{
// 閿姣佹墍鏈夊瓙鎺т歡
WidgetSet temp(std::move(pImpl_->children_));
std::for_each(temp.begin(), temp.end(), std::mem_fn(&Widget::Destroy));
if (IsRoot())
{
// 浣滀負鏍規帶浠訛紝鍚屾椂閿姣侀┍鍔?/span>
delete pImpl_->pDriver_;
}
else
{
// 涓嶆槸鏍規帶浠訛紝鍒欒劚紱葷埗鎺т歡
SetParent(0);
}
delete pImpl_;
}
{
RECT clientRect;
::GetClientRect(param.hWnd, &clientRect);
pRootWidget->SetAbsoluteRect(clientRect, false);
}
break;
void SetAbsoluteRect(const RECT& rect, bool update = true);
{
// 浣跨敤鍐呭瓨DC鏉ョ紦鍐茬粯鍒?br> // 鐩墠娌℃湁璁$畻鑴忕煩褰㈠尯鍩?/span>
wnd_msg_assistant::OnPaint opAssistant(param.hWnd);
pRootWidget->Draw(opAssistant.GetMemDC());
}
return S_OK;
· 鑻規灉iPad 2閫氳繃3C璁よ瘉 鏈鏅?鏈堝浗鍐呬笂甯?/a>(2011-04-10 09:18)
· 鐩茬洰渚濊禆iPhone絳夊伐鍏峰鑸?鑻卞浗椹村弸榪瘋礬澶?/a>(2011-04-10 09:14)
· 瓚h皥錛氭兂鎷呬換CEO鐨勮瘽錛屾渶濂芥槸鍘昏嫻鏋滃伐浣滐紝鍏舵鏄井杞紝鍐嶆墠鏄疓oogle(2011-04-10 08:26)
· 鑵捐灝嗗緩绔嬫柊鏁版嵁涓績錛岃妯′負鑻規灉鐨勪袱鍊?/a>(2011-04-10 08:25)
· 杞婚噺鍖栫殑寰瀷鍗氬Tumblr(2011-04-10 08:03)
緗戠珯瀵艱埅錛?a target="_blank">鍗氬鍥欏?/a> 鎴戠殑鍥瓙 鏂伴椈 闂瓨 灝忕粍 鍗氶棶 鐭ヨ瘑搴?/a>
闅愯棌椹卞姩綾伙細
涓轟簡璁╃敤鎴鋒湁鏇寸畝鍗曠殑浣跨敤鎺ュ彛錛屾垜浠渶瑕佹妸涓嶅繀瑕佺殑涓滆タ榪涜涓瀹氱殑闅愯棌銆傚墠闈㈡垜灝辨彁鍒癢idgetDriver瀵逛簬鐢ㄦ埛鏉ヨ鏄笉鍏沖績鐨勪笢瑗匡紝閭d箞鎴戜滑灝卞皢鍏惰繘琛岄殣钘忋?/p>
銆銆鏂規1錛?/strong>
銆銆灝哤idgetDriver鏀懼埌Widget.cpp涓紝榪欐牱鐨勯殣钘忔柟寮忔槸鏈涓ュ瘑鐨勶紝瀵逛簬鐢ㄦ埛鏉ヨ瀹屽叏鐪嬩笉鍒癢idgetDriver銆備絾鏄殢鐫鎴戜滑鐨勫疄鐜拌啫鑳錛岃繖浼氳鎴戜滑鐨刉idget.cpp鍙樺緱闈炲父鑷冭偪銆?/p>
銆銆鏂規2錛?/strong>
銆銆涓嶆敼鍙樻枃浠剁粨鏋勶紝灝哤idgetDriver縐佹湁鍖栵紝閫氳繃鍙嬪厓澹版槑浣垮緱鍙湁Widget綾誨璞¤兘澶熻闂甒idgetDriver銆傝繖鏍風敤鎴瘋櫧鐒惰兘澶熺湅鍒癢idgetDriver榪欎釜綾誨畾涔夛紝浣嗘槸鍗存棤娉曚嬌鐢紝榪欐牱瀵逛簬浠g爜鐨勭粨鏋勭粍緇囦篃鏇存湁鍒┿?/p>
鎴戦噰鐢ㄤ簡鏂規2
class Driver_{
friend class Widget;
DriverImpl_* pImpl_;
private:
explicit Driver_(HWND hWnd);
~Driver_();
Driver_(const Driver_&);
Driver_& operator =(const Driver_&);
private:
void SetRootWidget(Widget* pRootWidget);
HWND GetContainerWindow() const;
Widget* GetRootWidget() const;
};
鍥犱負鎴戜滑闅愯棌浜哤idgetDriver錛岄偅涔堝畠鐨勮亴鑳藉氨鑳藉榪涜綆鍖栥傚墠闈㈡彁鍒扮殑鏍規帶浠跺拰WidgetDriver涔嬮棿鐨勫叧緋繪垜浠氨鑳藉鏀逛負褰撴柟闈㈡帶鍒朵簡銆備簬鏄垜灝哤idgetDriver鏀懼埌浜嗘牴鎺т歡涓繘琛岀鐞嗭紝鎴戜滑鍙渶瑕佹搷浣滄牴鎺т歡渚垮彲銆?/p>
Widget::Widget(HWND hWnd)
: pImpl_(new WidgetImpl)
{
pImpl_->pDriver = new widget::Driver_(hWnd);
pImpl_->pDriver->SetRootWidget(this);
}
Widget::~Widget()
{
if (IsRoot())
{
delete pImpl_->pDriver;
}
delete pImpl_;
}
鍓嶉潰鎴戜滑閮芥病鏈夋彁鍒板簲璇ヤ綍鏃剁粨鏉熸垜浠殑緋葷粺錛屼絾鏄垜浠殑緋葷粺鐢熷懡鍛ㄦ湡鍜岀獥鍙f槸鎭伅鐩稿叧鐨勶紝鍦ㄧ獥鍙i攢姣佺殑鏃跺欓偅涔堝拰榪欎釜紿楀彛鐩稿叧鑱旂殑鎺т歡浣撶郴灝卞簲璇ラ攢姣併備簬鏄垜浠娑堟伅榪囨護鍣ㄥ仛浜嗕竴鐐圭偣鏀瑰姩錛?/p>
LRESULT MessageFilter::Filter(const Param& param, Widget* pRootWidget)
{
assert(param.originalProc);
assert(pRootWidget);
#ifdef _DEBUG
std::stringstream ss;
ss<<"紿楀彛娑堟伅: "<<std::showbase<<std::hex<<param.message<<" 榪涘叆Widget娑堟伅榪囨護錛乗r\n";
::OutputDebugStringA(ss.str().c_str());
#endif // _DEBUG
LRESULT ret = ::CallWindowProc(
param.originalProc,
param.hWnd,
param.message,
param.wParam,
param.lParam);
if (WM_DESTROY == param.message)
{
// 閿姣佹牴鎺т歡
pRootWidget->Destroy();
}
return ret;
}
涓嬩竴姝ユ垜浠究瑕佸紑濮嬪鎴戜滑鐨勬帶浠惰繘琛岃璁′簡錛屾垜浠嚜濮嬭嚦緇堥兘灝嗘帶浠舵娊璞′負紿楀彛瀹㈡埛鍖虹殑涓涓尯鍩燂紝鎵浠ヨ鎴戜滑騫朵笉鎵撶畻浣跨敤緇ф壙鏉ユ墿灞曟帶浠躲傚悗闈細鐪嬪埌鎴戜滑浣跨敤鎻掑叆寮忕殑鎵╁睍錛岃繖鏍風殑鏂瑰紡鍏峰鍔ㄦ佹浛鎹㈢殑鑳藉姏鐢氳嚦榪樿兘灝嗕竴涓墿灞曞叡浜粰澶氫釜鎺т歡浣跨敤銆?/p>
浣滆? Evil.Ghost 鍙戣〃浜?2011-04-07 20:55 鍘熸枃閾炬帴
鏈鏂版柊闂伙細
· 鑻規灉iPad 2閫氳繃3C璁よ瘉 鏈鏅?鏈堝浗鍐呬笂甯?/a>(2011-04-10 09:18)
· 鐩茬洰渚濊禆iPhone絳夊伐鍏峰鑸?鑻卞浗椹村弸榪瘋礬澶?/a>(2011-04-10 09:14)
· 瓚h皥錛氭兂鎷呬換CEO鐨勮瘽錛屾渶濂芥槸鍘昏嫻鏋滃伐浣滐紝鍏舵鏄井杞紝鍐嶆墠鏄疓oogle(2011-04-10 08:26)
· 鑵捐灝嗗緩绔嬫柊鏁版嵁涓績錛岃妯′負鑻規灉鐨勪袱鍊?/a>(2011-04-10 08:25)
· 杞婚噺鍖栫殑寰瀷鍗氬Tumblr(2011-04-10 08:03)
緙栬緫鎺ㄨ崘錛?a target="_blank">闈炴垬涔嬬姜錛屼粠姘鎬腑Office璋堣搗
緗戠珯瀵艱埅錛?a target="_blank">鍗氬鍥欏?/a> 鎴戠殑鍥瓙 鏂伴椈 闂瓨 灝忕粍 鍗氶棶 鐭ヨ瘑搴?/a>
紿楀彛銆佹帶浠墮┍鍔ㄣ佹牴鎺т歡涔嬮棿鐨勫叧緋?/strong>
鍓嶉潰鎴戜滑宸茬粡璇翠簡錛屼竴涓獥鍙e彧鑳藉叧鑱斾竴涓帶浠墮┍鍔紝涓涓帶浠墮┍鍔ㄤ篃鍚屾牱瀵瑰簲涓涓牴鎺т歡銆備負浠涔堝憿錛熷洜涓烘垜浠殑椹卞姩闇瑕佷綔鐢ㄤ簬涓涓帶浠朵綋緋伙紝涓涓帶浠朵綋緋誨叿鏈変竴涓牴鎺т歡錛岃繖涓牴鎺т歡綆$悊浜嗘暣涓獥鍙g殑瀹㈡埛鍖恒傝繖鏍鋒垜浠墠鑳藉湪榪欎釜鏍規帶浠朵笅鍒涘緩浠繪剰鐨勬帶浠訛紝騫舵椿鍔ㄥ湪紿楀彛瀹㈡埛鍖恒?/p>
鐢熷懡鍛ㄦ湡鎺у埗
鍩轟簬涓婇潰鐨勫叧緋伙紝鎺т歡椹卞姩鍜屾牴鎺т歡鐨勭敓鍛芥伅鎭浉鍏籌紝閭d箞鎴戜滑璁╁叾鐩鎬簰鍒剁害銆傛棦鐒舵槸浠栦滑鑷韓鐩鎬簰鍒剁害錛岄偅涔堢敤鎴峰氨涓嶅簲璇ョ鐞嗗叾鐢熷懡鍛ㄦ湡錛屾垜浠壒鎰忓紩鍏ヤ竴涓畝鍗曠殑瀵硅薄姹犳潵綆$悊錛屽茍鐢ㄨ闂帶鍒舵潵閬垮厤澶栭儴鐩存帴鏋勯犮?/p>
private:
explicit Widget(widget::Driver* pDriver);
~Widget();
Widget(const Widget&);
Widget& operator =(const Widget&);
// 璁╁璞℃睜鑳藉鍒涘緩Widget瀵硅薄
friend class ObjectPool<Widget>;
#pragma warning(push)
#pragma warning(disable:4396)
friend void std::_Destroy(Widget _FARQ *);
#pragma warning(pop)
public:
static Widget* Create(HWND hWnd); // 鍒涘緩鏍規帶浠?/span>
void Destroy();
鎴戜滑鎻愪緵浜嗕竴涓潤鎬佹帴鍙reate鐢ㄤ簬鍒涘緩鏍規帶浠訛紝鍙互娉ㄦ剰鍒扮殑涓鐐規槸鍙傛暟鏄獥鍙e彞鏌勩傚叾瀹炵敤鎴峰浜庝粈涔堥┍鍔ㄣ佷粈涔堣繃婊ょ殑閮戒笉鍏沖績錛岀敤鎴峰彧鍏沖績鎺т歡浣撶郴錛屾墍浠ヨ鎴戜滑鍙互閫氳繃榪欎釜鎺ュ彛閫忔槑鐨勫垱寤烘牴緇勪歡錛屽疄鐜頒腑浼氳嚜鍔ㄧ殑鍘婚┍鍔ㄦ紿楀彛銆?/p>
Widget* Widget::Create(HWND hWnd)
{
return GetWidgetPool_().Construct(widget::Driver::Create(hWnd));
}
椹卞姩鏋勯犳椂浼氬垱寤烘牴鎺т歡錛屾瀽鏋勬椂閿姣佹牴鎺т歡
Driver::Driver(HWND hWnd)
: pImpl_(new DriverImpl(hWnd))
{
// 鍒涘緩鏍規帶浠?/span>
pImpl_->SetRootWidget(Widget::Create_(this));
}
~DriverImpl()
{
// 閿姣佹牴鎺т歡
Widget* pOldRootWidget = GetRootWidget();
pRootWidget_ = 0;
if (pOldRootWidget)
{
pOldRootWidget->Destroy();
}
}
鍚屾牱錛屾牴鎺т歡鏋愭瀯鏃朵篃閿姣佹帶浠墮┍鍔?/p>
Widget::~Widget()
{
if (IsRoot())
{
pImpl_->GetDriver()->Destroy();
}
delete pImpl_;
}
榪欐牱錛岀敤鎴峰叾瀹炴湁涓や釜鍏ュ彛鍙互榪涘叆鍒版垜浠殑鎺т歡緋葷粺錛屼竴涓槸閫氳繃鎺т歡椹卞姩錛屼竴涓槸閫氳繃鎺т歡鏈韓銆傛垜浠彁鍊$敤鎴蜂笉鍘誨叧蹇冩帶浠墮┍鍔ㄣ傞偅涔堢敋鑷蟲垜浠彲浠ラ殣钘廌river榪欎釜綾伙紝鐩墠鎴戞病鏈夎繖鏍峰仛銆?/p>
浣滆? Evil.Ghost 鍙戣〃浜?2011-04-06 21:21 鍘熸枃閾炬帴
鏈鏂版柊闂伙細
· 鑻規灉iPad 2閫氳繃3C璁よ瘉 鏈鏅?鏈堝浗鍐呬笂甯?/a>(2011-04-10 09:18)
· 鐩茬洰渚濊禆iPhone絳夊伐鍏峰鑸?鑻卞浗椹村弸榪瘋礬澶?/a>(2011-04-10 09:14)
· 瓚h皥錛氭兂鎷呬換CEO鐨勮瘽錛屾渶濂芥槸鍘昏嫻鏋滃伐浣滐紝鍏舵鏄井杞紝鍐嶆墠鏄疓oogle(2011-04-10 08:26)
· 鑵捐灝嗗緩绔嬫柊鏁版嵁涓績錛岃妯′負鑻規灉鐨勪袱鍊?/a>(2011-04-10 08:25)
· 杞婚噺鍖栫殑寰瀷鍗氬Tumblr(2011-04-10 08:03)
緙栬緫鎺ㄨ崘錛?a target="_blank">闈炴垬涔嬬姜錛屼粠姘鎬腑Office璋堣搗
緗戠珯瀵艱埅錛?a target="_blank">鍗氬鍥欏?/a> 鎴戠殑鍥瓙 鏂伴椈 闂瓨 灝忕粍 鍗氶棶 鐭ヨ瘑搴?/a>
鍓嶉潰鎴戜滑鍒╃敤鐜版湁鐨勫井杞疉TL瀹炵幇鐨則hunk宸茬粡涓烘垜浠埅鑾風獥鍙f秷鎭仛濂戒簡鍑嗗錛屾鍒繪垜浠簲璇ョ紪鍐欐垜浠殑Widget椹卞姩鐨勫垵姝ュ疄鐜頒簡銆?/p>
鍒╃敤thunk瀵圭獥鍙f秷鎭繃紼嬭繘琛屽瓙綾誨寲錛岄偅涔堢獥鍙f秷鎭氨浼氬厛嫻佸叆鍒版垜浠殑Widget椹卞姩瀵硅薄錛學idget椹卞姩瀵硅薄璐熻矗灝嗘秷鎭紶閫掔粰娑堟伅榪囨護鍣ㄣ傜幇鍦ㄦ垜浠殑娑堟伅榪囨護鍣ㄨ繕鏈疄鐜幫紝浜庢槸鎴戜滑鎵撳嵃浜嗚繘鍏ユ秷鎭繃婊ゅ櫒鐨勬秷鎭疘D鍊間互瑙傚療娑堟伅鐨勬祦鍔ㄦ儏鍐點?/p>
浠ヤ笅鏄垜浠殑Widget椹卞姩綾伙紝鎴戜滑灝嗗叾鏀懼叆浜嗕竴涓悕涓簑idget鐨勫悕瀛楃┖闂翠腑錛屼互鍚庢垜浠瑆idget鐩稿叧鐨勫悕瀛楅兘浼氭斁鍏ュ埌榪欎釜鍚嶅瓧絀洪棿涓?/p>
class DriverImpl;
class Driver{
DriverImpl* pImpl_;
public:
explicit Driver(HWND hWnd);
~Driver();
private:
Driver(const Driver&);
Driver& operator =(const Driver&);
public:
inline HWND GetContainerWindow() const;
};
鍥犱負Driver鐨勫疄鐜版垜浠茍涓嶅叧蹇冿紝鎵浠ユ垜浠皢鍏跺疄鐜拌繘琛屼簡涓涓殣钘忥紝榪欐牱涔熶究浜庢垜浠慨鏀瑰叾瀹炵幇鏂瑰紡銆侱river綾誨璞¤姹傜敤浜庢瀯閫犲畠鐨勭獥鍙e彞鏌勫繀欏諱負鏈夋晥鐨勭獥鍙e彞鏌勶紝騫朵笖姣忎釜紿楀彛鍙ユ焺鍙兘琚┍鍔ㄤ竴嬈★紝鎵浠ユ垜浠湪璋冭瘯鐗堟湰涓仛浜嗘柇璦鏉ョ害鏉熸垜浠殑緙栫爜錛屽湪鍙戝竷鐗堟湰涓笉浼氬仛浠諱綍鍒ゆ柇銆?/p>
#ifdef _DEBUG
assert(::IsWindow(hContainerWnd_));
// 涓嶈兘澶氭椹卞姩鍚屼竴紿楀彛
assert(GetContainerWindows_().insert(hContainerWnd_).second);
#endif // _DEBUG
鐜板湪鎴戜滑瀹炵幇鐨凞river鎺ュ彛闈炲父綆鍗曪紝鍙湁涓涓瀯閫犳帴鍙e拰鏌ヨ鍏墮┍鍔ㄧ殑紿楀彛鍙ユ焺鐨勬帴鍙o紝鏄劇劧娌℃湁浠諱綍鍙互鎺у埗椹卞姩鎴栬呰В闄ら┍鍔ㄧ殑鏈轟細錛屾澶勬垜浠厛鏀句竴鏀撅紝鍥犱負榪欏湪浠ュ悗浼氭秹鍙婂埌榪欎釜椹卞姩鎵鍏寵仈鐨刉idget浣撶郴鐨勪竴浜涢棶棰樸?/p>
閫氳繃thunk鎴幏鐨勭獥鍙f秷鎭皢浼氳繘鍏ュ埌Driver瀹炵幇涓紝Driver鐨勫姛鑳戒粎浠呮槸浣滀負Widget鐨勯┍鍔紙涔熷氨鏄秷鎭┍鍔級錛屽畠涓嶈礋璐d換浣曟秷鎭殑澶勭悊錛屾墍浠ヨ繖涓獥鍙h繃紼嬪湪鎴幏鍒扮獥鍙f秷鎭悗绔嬪嵆浜ょ敱娑堟伅榪囨護澶勭悊銆?/p>
LRESULT WndProc_(UINT message, WPARAM wParam, LPARAM lParam)
{
// 榪涜娑堟伅榪囨護
MessageFilter::Param param;
param.hWnd = hContainerWnd_;
param.originalProc = originalProc_;
param.message = message;
param.wParam = wParam;
param.lParam = lParam;
return MessageFilter::Filter(param);
}
榪欓噷娑堟伅榪囨護鍣ㄧ殑瀹炵幇涓嶅湪榪欎竴孌佃璁轟箣涓紝鎵浠ユ垜浠畝鍗曠殑浠ヤ竴涓被闈欐佹帴鍙f潵浣滀負榪囨護鍏ュ彛銆?/p>
濂戒簡錛屾垜浠埌榪欓噷宸茬粡寮鍚簡Widget鍐呮牳鐨勮繍浣滅郴緇熺殑瀹炵幇錛屼粠嫻嬭瘯宸ョ▼涓劅鍙楀緱鍒頒竴瀹氱殑浣撻獙浜嗐?/p>
浣滆? Evil.Ghost 鍙戣〃浜?2011-04-03 13:56 鍘熸枃閾炬帴
鏈鏂版柊闂伙細
· 鑻規灉iPad 2閫氳繃3C璁よ瘉 鏈鏅?鏈堝浗鍐呬笂甯?/a>(2011-04-10 09:18)
· 鐩茬洰渚濊禆iPhone絳夊伐鍏峰鑸?鑻卞浗椹村弸榪瘋礬澶?/a>(2011-04-10 09:14)
· 瓚h皥錛氭兂鎷呬換CEO鐨勮瘽錛屾渶濂芥槸鍘昏嫻鏋滃伐浣滐紝鍏舵鏄井杞紝鍐嶆墠鏄疓oogle(2011-04-10 08:26)
· 鑵捐灝嗗緩绔嬫柊鏁版嵁涓績錛岃妯′負鑻規灉鐨勪袱鍊?/a>(2011-04-10 08:25)
· 杞婚噺鍖栫殑寰瀷鍗氬Tumblr(2011-04-10 08:03)
緙栬緫鎺ㄨ崘錛?a target="_blank">闈炴垬涔嬬姜錛屼粠姘鎬腑Office璋堣搗
緗戠珯瀵艱埅錛?a target="_blank">鍗氬鍥欏?/a> 鎴戠殑鍥瓙 鏂伴椈 闂瓨 灝忕粍 鍗氶棶 鐭ヨ瘑搴?/a>
瀹炵幇Window Proc Thunk錛?/strong>
灝卞ソ鍍忔按娉典竴鏍鳳紝鎴戜滑鐨勭郴緇熶篃闇瑕佷竴涓車鈥斺旀秷鎭車錛屼篃灝辨槸鍓嶉潰鍥句笂鐨凪essage Driver銆傝繖涓狣river鐨勫彲浠ヤ緷闈犱竴涓猈indow Proc Thunk鏉ユ埅鑾風獥鍙f秷鎭紝閭d箞鎴戜滑寰楀厛瀹炵幇涓涓猈indow Proc Thunk銆?/p>
榪欓噷鎴戦夋嫨鐨勬柟娉曟槸鎷跨幇鎴愮殑浠g爜鏉ョ敤錛屽井杞疉TL妗嗘灦涓彁渚涙湁thunk鐨勫疄鐜幫紝鎴戝皢鍏舵彁鍙栧嚭鏉ョ◢鍔犱慨鏀瑰氨鑳戒負鎴戜滑鎵鐢ㄤ簡銆?/p>
浠ヤ笅鏄叾瀹炵幇鐨勪竴鐐逛唬鐮佺墖孌碉細
void* __stdcall AllocStdCallThunk(void);
void __stdcall FreeStdCallThunk(void*);
#pragma pack(push, 1)
class StdCallThunk_{
DWORD mov_; // mov dword ptr [esp+0x4], this_ (esp+0x4灝辨槸絎竴涓弬鏁?
DWORD this_; //
BYTE jmp_; // jmp proc
DWORD relproc_; // relative jmp
public:
bool Init(DWORD_PTR proc, void* pThis)
{
mov_ = 0x042444C7; //C7 44 24 0C
this_ = PtrToUlong(pThis);
jmp_ = 0xe9;
relproc_ = DWORD((INT_PTR)proc - ((INT_PTR)this+sizeof(StdCallThunk_)));
// 鐢ㄨ嚜韜洿鏂版寚浠ょ紦瀛?/span>
return ::FlushInstructionCache(::GetCurrentProcess(), this, sizeof(StdCallThunk_)) ? true : false;
}
// 鏌愪簺thunk灝嗗姩鎬佺殑涓轟唬鐮佸垎閰嶅唴瀛?/span>
void* GetCodeAddress()
{
return this;
}
void* operator new(size_t)
{
return AllocStdCallThunk();
}
void operator delete(void* pThunk)
{
FreeStdCallThunk(pThunk);
}
};
#pragma pack(pop)
浣滆? Evil.Ghost 鍙戣〃浜?2011-04-03 13:55 鍘熸枃閾炬帴
鏈鏂版柊闂伙細
· 鑻規灉iPad 2閫氳繃3C璁よ瘉 鏈鏅?鏈堝浗鍐呬笂甯?/a>(2011-04-10 09:18)
· 鐩茬洰渚濊禆iPhone絳夊伐鍏峰鑸?鑻卞浗椹村弸榪瘋礬澶?/a>(2011-04-10 09:14)
· 瓚h皥錛氭兂鎷呬換CEO鐨勮瘽錛屾渶濂芥槸鍘昏嫻鏋滃伐浣滐紝鍏舵鏄井杞紝鍐嶆墠鏄疓oogle(2011-04-10 08:26)
· 鑵捐灝嗗緩绔嬫柊鏁版嵁涓績錛岃妯′負鑻規灉鐨勪袱鍊?/a>(2011-04-10 08:25)
· 杞婚噺鍖栫殑寰瀷鍗氬Tumblr(2011-04-10 08:03)
緙栬緫鎺ㄨ崘錛?a target="_blank">闈炴垬涔嬬姜錛屼粠姘鎬腑Office璋堣搗
緗戠珯瀵艱埅錛?a target="_blank">鍗氬鍥欏?/a> 鎴戠殑鍥瓙 鏂伴椈 闂瓨 灝忕粍 鍗氶棶 鐭ヨ瘑搴?/a>
鐩爣錛?/strong>
瀹炵幇涓濂梬indows涓嬬畝鍗曚笖鍙墿灞曠殑鎶借薄妯℃嫙鎺т歡鍐呮牳銆?/p>
鎶借薄妯℃嫙鎺т歡錛?/strong>
鎴戜滑灝唚indows緋葷粺鐨勭獥鍙e鎴峰尯浣滀負妯℃嫙鎺т歡鐨勫鍣紝姣忎釜妯℃嫙鎺т歡灝辨槸鍏朵腑鐨勪竴涓娊璞$煩褰㈠尯鍩燂紝騫朵笖鑳藉妯℃嫙鎺т歡榪涜閫掑綊宓屽銆傛帶浠舵敮鎸佸熀鏈殑榧犳爣鍜岄敭鐩樻秷鎭紝鑳藉鍦ㄧ獥鍙eぇ灝忔敼鍙樻椂榪涜甯冨眬銆?/p>
鍒嗘瀽錛?/strong>
鍥犱負鎴戜滑瑕佸疄鐜扮殑鏄娊璞$殑妯℃嫙鎺т歡錛屼笉鏄湡姝g殑紿楀彛鎺т歡錛岄偅涔堝氨闇瑕佸皢紿楀彛娑堟伅閫傛椂媧懼彂鍒扮浉搴旀帶浠躲備笅闈互涓涓浘鏉ヨ鍒掔獥鍙f秷鎭殑嫻佸悜銆?/p>
鍦ㄨ繖涓浘涓婃垜浠彲浠ョ湅鍒伴櫎浜嗘垜浠殑鎺т歡浣撶郴浠ュ榪橀渶瑕佸疄鐜板嚑涓牳蹇冩ā鍧楁潵椹卞姩鎺т歡銆備粬浠垎鍒槸錛氭秷鎭┍鍔ㄣ佹秷鎭繃婊ゃ佹秷鎭漿鎹€傛秷鎭┍鍔ㄩ氳繃鏌愮鏂規硶鎴幏紿楀彛娑堟伅錛堝浘涓婁嬌鐢╰hunk錛夛紝鐒跺悗灝嗙獥鍙f秷鎭氦緇欒繃婊ゅ櫒榪涜榪囨護錛堝洜涓烘ā鎷熸帶浠朵笉鏄墍鏈夌獥鍙f秷鎭兘鎰熷叴瓚o級錛屾秷鎭繃婊ゅ嚭鎺т歡鎰熷叴瓚g殑娑堟伅浜ょ粰娑堟伅杞崲鍣紝鍏朵粬娑堟伅浜よ繕緇欑獥鍙g殑鍘熸湁紿楀彛榪囩▼榪涜澶勭悊錛?strong>姝ゅ瑕佹敞鎰忕殑鏄秷鎭繃婊ゅ悗鎺т歡鎰熷叴瓚g殑娑堟伅涓嶄細鍐嶅洖鍒板師紿楀彛榪囩▼錛夈傛秷鎭漿鎹㈠櫒灝嗙獥鍙f秷鎭漿鎹負鎺т歡娑堟伅錛屼箣鎵浠ヨ榪涜杞崲鏄洜涓烘帶浠朵綋緋誨彲鑳芥敮鎸佺殑娑堟伅緋葷粺浼氭湁鍒簬紿楀彛娑堟伅錛屼篃鍙兘闇瑕佽繘琛屽潗鏍囨槧灝勭瓑銆?/p>
鍥句笂榪樿兘鐪嬪埌錛屾垜浠殑鎺т歡鏄兘澶熼掑綊宓屽鐨勩傛瘡涓獥鍙e搴斾竴涓牴鎺т歡錛屾墍鏈夌殑鎺т歡閮芥槸鍦ㄨ繖涓牴緇勪歡涔嬩腑鐨勩備負浜嗚鑳藉浣跨敤紿楀彛鐨勬暣涓鎴峰尯錛岄偅涔堟牴緇勪歡鎵澶勫尯鍩熷氨鏄獥鍙g殑鏁翠釜瀹㈡埛鍖恒?/p>
鐜板湪鎴戜滑瑕佸紑濮嬭繘琛岃璁′簡錛岃璁¤繃紼嬩腑灝嗗紩鍏ヤ唬鐮侊紝浠g爜灝嗛殢鐫璁捐鐨勬紨鍖栬繘琛屾紨鍖栵紝鏈緇堝艦鎴愭垜浠繖涓畝鍗曚笖鍙墿灞曠殑鎶借薄妯℃嫙鎺т歡鏍稿績銆?/p>
浣滆? Evil.Ghost 鍙戣〃浜?2011-04-03 13:53 鍘熸枃閾炬帴
鏈鏂版柊闂伙細
· 鑻規灉iPad 2閫氳繃3C璁よ瘉 鏈鏅?鏈堝浗鍐呬笂甯?/a>(2011-04-10 09:18)
· 鐩茬洰渚濊禆iPhone絳夊伐鍏峰鑸?鑻卞浗椹村弸榪瘋礬澶?/a>(2011-04-10 09:14)
· 瓚h皥錛氭兂鎷呬換CEO鐨勮瘽錛屾渶濂芥槸鍘昏嫻鏋滃伐浣滐紝鍏舵鏄井杞紝鍐嶆墠鏄疓oogle(2011-04-10 08:26)
· 鑵捐灝嗗緩绔嬫柊鏁版嵁涓績錛岃妯′負鑻規灉鐨勪袱鍊?/a>(2011-04-10 08:25)
· 杞婚噺鍖栫殑寰瀷鍗氬Tumblr(2011-04-10 08:03)
緙栬緫鎺ㄨ崘錛?a target="_blank">闈炴垬涔嬬姜錛屼粠姘鎬腑Office璋堣搗
緗戠珯瀵艱埅錛?a target="_blank">鍗氬鍥欏?/a> 鎴戠殑鍥瓙 鏂伴椈 闂瓨 灝忕粍 鍗氶棶 鐭ヨ瘑搴?/a>