Files
AC_Pro/MenuUnit.cpp
2026-06-13 00:05:19 +08:00

1108 lines
26 KiB
C++

//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "MenuUnit.h"
#include "MessageDef.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#include "GlobalUnit.h"
//---------------------------------------------------------------------------
#define CLR_BORDER RGB( 100, 108, 119 )
#define CLR_BORDER_HOT RGB( 30, 32, 36 )
#define CLR_BKGRND_NOR RGB( 39, 42, 47 )
#define CLR_BKGRND_HOT RGB( 67, 73, 80 )
#define CLR_TXT_NOR RGB( 213, 221, 232 )
#define CLR_TXT_DISABLE RGB( 100, 108, 119 )
#define CLR_BREAK RGB( 100, 108, 119 )
#define CLR_BOARD_FILL RGB( 76, 82, 91 )
#define WIDTH_MIN 65
#define WIDTH_MAX 525
#define TOP_HEIGHT 5
#define HEIGHT_BREAK 5
#define IMG_WIDTH 32
#define TRI_WIDTH 16
#define OFFSET_X 6
#define OFFSET_Y 5
#define OFFSET_SEL 3
//---------------------------------------------------------------------------
String __fastcall CutDirString(TCanvas *ACanvas, String strDir, int nWidth)
{
String str = strDir;
AnsiString strText;
if( ACanvas->TextWidth( str ) > nWidth ){ //超出宽
strText = str.SubString(1, 3);
nWidth -= ACanvas->TextWidth(strText);
//-----------------取出文件夹与文件名字-----------------------------
int istart=1,iend=1;
UnicodeString strShorty = str.SubString(4, str.Length());
System::DynamicArray<UnicodeString> DStr;
for( int i=1;i<=strShorty.Length();i++ ){
if( strShorty[i]== '\\' ){
iend = i;
DStr.Length++;
DStr[DStr.Length-1] = strShorty.SubString(istart,iend-istart);
istart = iend+1;
}
}
DStr.Length++;
DStr[DStr.Length-1] = strShorty.SubString(istart,str.Length()-istart);
//如果 C:/ + 文件名大于最大宽度 或者 C:/ + ... + 文件名大于最大宽度
if( ACanvas->TextWidth( strText+DStr[DStr.Length-1] ) > nWidth
||( DStr.Length>1 && ACanvas->TextWidth( strText+"...\\"+DStr[DStr.Length-1] )>nWidth ) )
{
strText = strText + "...";
while( ACanvas->TextWidth( strShorty )>nWidth ){
strShorty = strShorty.SubString( 2, strShorty.Length() );
}
strText += strShorty;
}
else{
struct Pos{
int id;
int Length;
};
Pos temPos[20]; //*********里面个数表示最大支持文件数
for( int i=0;i<DStr.Length-1;i++ ){
temPos[i].id=i;
temPos[i].Length = ACanvas->TextWidth( DStr[i] );
}
for( int i=0;i<DStr.Length-1;i++ ){
for(int j=0;j<DStr.Length-1;j++){
if( temPos[i].Length>temPos[j].Length ){
Pos temp = temPos[i];
temPos[i] = temPos[j];
temPos[j] = temp;
}
}
}
int iPos=0;
AnsiString temstrText = str;
while( ACanvas->TextWidth(temstrText)>nWidth ){
if(iPos>DStr.Length-2)
break;
temstrText = strText;
if(ACanvas->TextWidth(DStr[temPos[iPos].id])>ACanvas->TextWidth(DStr[temPos[iPos].id].SubString( 1,2 ) + "..."))
DStr[temPos[iPos].id] = DStr[temPos[iPos].id].SubString( 1,2 ) + "...";
iPos++;
for( int i=0;i<DStr.Length-1;i++ ){
temstrText += DStr[i];
temstrText +="\\";
}
temstrText +=DStr[DStr.Length-1];
}
iPos=0;
while( ACanvas->TextWidth(temstrText)>nWidth ){
if(iPos>DStr.Length-2)
break;
temstrText = strText;
if(iPos==0 )
DStr[iPos] = "...";
else
DStr[iPos] = "";
iPos++;
for( int i=0;i<DStr.Length-1;i++ ){
temstrText += DStr[i];
if(DStr[i]!="")
temstrText +="\\";
}
temstrText +=DStr[DStr.Length-1];
}
strText = temstrText;
}
DStr.Length=0;
}
else
strText = str;
return strText;
}
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* * * * * * * * * * * * * * * * * *CMenuItem * * * * * * * * * * * * * * * * *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
//---------------------------------------------------------------------------
__fastcall CMenuItem::CMenuItem(String strCaption, String strHotkey, TNotifyEvent aClickEvent,
int idMenu, TPngImage *pPic )
{
Caption = strCaption;
Hotkey = strHotkey;
OnClick = aClickEvent;
if( pPic ) {
FIcon = new TPngImage();
FIcon->Assign(pPic);
}
FSubItems = new System::Classes::TList();
Parent = NULL;
FEnabled = true;
FSelected = false;
FBreak = !Caption.Compare("-");
FMenuID = idMenu;
}
//---------------------------------------------------------------------------
__fastcall CMenuItem::~CMenuItem()
{
ClearSubItems();
SAFE_DELETE(FSubItems);
SAFE_DELETE(FIcon)
}
//---------------------------------------------------------------------------
void __fastcall CMenuItem::AddItem( CMenuItem *Item )
{
FSubItems->Add( Item );
Item->Parent = this;
// HasSubItem = true;
// FCaption->
}
//---------------------------------------------------------------------------
void __fastcall CMenuItem::ClearSubItems()
{
for( int i=0; i<FSubItems->Count; i++ ){
CMenuItem *pItem = (CMenuItem *)FSubItems->Items[i];
SAFE_DELETE(pItem)
}
FSubItems->Clear();
}
//---------------------------------------------------------------------------
CMenuItem* __fastcall CMenuItem::AppendMenu( String strCaption, String strHotkey,
TNotifyEvent aClickEvent, int idMenu, TPngImage *pPic )
{
CMenuItem * pItem = new CMenuItem(strCaption, strHotkey, aClickEvent, idMenu, pPic);
pItem->OnDrawItem = FDrawItem;
FSubItems->Add( pItem );
return pItem;
}
//---------------------------------------------------------------------------
void __fastcall CMenuItem::CreateSubMenu( TMenuPanel* pSubMenu )
{
for( int i=0; i<FSubItems->Count; i++ )
((CMenuItem*)FSubItems->Items[i])->Selected = false;
pSubMenu->SetMenuItems( FSubItems );
}
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* * * * * * * * * * * * * * * * * *TMenuPanel * * * * * * * * * * * * * * * * *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
//---------------------------------------------------------------------------
#define STATE_NONE -1
#define STATE_NORMAL 0
#define STATE_HOVER 1
#define STATE_DOWN 2
#define STATE_DISABLE 3
TPngImage *u_imgSubMenu = NULL,
*u_imgUp = NULL,
*u_imgDown = NULL;
TApplicationEvents *u_AppEvent = NULL;
TTimer *u_pTimer = NULL; //自动滚屏定时器
__fastcall TMenuPanel::TMenuPanel(TComponent* Owner, int iType )
: Vcl::Extctrls::TPanel(Owner)
{
Visible = false;
m_iType = iType;
Width = 90;
Height = 2*TOP_HEIGHT;
m_Items = NULL;
m_ItemHeight = 20;
m_iSelected = -1;
m_iFirst = 0;
m_iUpState = m_iDownState = STATE_NONE;
m_SubMenu = m_SupMenu = NULL;
// m_AppEvent = NULL;
// m_pTimer = NULL;
}
//---------------------------------------------------------------------------
__fastcall TMenuPanel::~TMenuPanel()
{
ClearAll();
if( m_iType==0 )
ReleaseCapture();
if( !m_SupMenu )
SAFE_DELETE(m_Items);
if( u_AppEvent )
u_AppEvent->OnMessage = NULL;
}
//---------------------------------------------------------------------------
void TMenuPanel::LoadResources()
{
if( !u_imgSubMenu ){
u_imgSubMenu = new TPngImage();
u_imgSubMenu->LoadFromResourceName(int(HInstance), L"ImgSubMenu");
}
if( !u_imgUp ){
u_imgUp = new TPngImage();
u_imgUp->LoadFromResourceName(int(HInstance), L"ImgUpMenu");
}
if( !u_imgDown ){
u_imgDown = new TPngImage();
u_imgDown->LoadFromResourceName(int(HInstance), L"ImgDownMenu");
}
u_AppEvent = new TApplicationEvents(Application->MainForm);
}
//---------------------------------------------------------------------------
void TMenuPanel::FreeResources()
{
SAFE_DELETE( u_imgSubMenu );
SAFE_DELETE( u_imgUp );
SAFE_DELETE( u_imgDown );
SAFE_DELETE( u_AppEvent );
SAFE_DELETE( u_pTimer );
}
//---------------------------------------------------------------------------
void __fastcall TMenuPanel::ClearAll()
{
m_ItemHeight = 20;
m_iSelected = -1;
m_iFirst = 0;
m_iUpState = m_iDownState = STATE_NONE;
if( !m_SupMenu && m_Items ){
for( int i=0; i<m_Items->Count; i++ ){
CMenuItem *pItem = (CMenuItem *)m_Items->Items[i];
SAFE_DELETE(pItem)
}
m_Items->Clear();
}
SAFE_DELETE(m_SubMenu)
}
//---------------------------------------------------------------------------
CMenuItem* __fastcall TMenuPanel::CreateMenu( String strCaption, String strHotkey,
TNotifyEvent aClickEvent, int idMenu, TPngImage *pPic )
{
CMenuItem * pItem = new CMenuItem(strCaption, strHotkey, aClickEvent, idMenu, pPic);
pItem->OnDrawItem = DrawItem;
if( !m_Items )
m_Items = new System::Classes::TList();
m_Items->Add( pItem );
return pItem;
}
//---------------------------------------------------------------------------
void __fastcall TMenuPanel::ShowSubMenu(CMenuItem *pItem, int iTop)
{
if( !m_SubMenu ){
m_SubMenu = new TMenuPanel( NULL, m_iType );
m_SubMenu->Parent = Parent;
m_SubMenu->m_SupMenu = this;
pItem->CreateSubMenu( m_SubMenu );
}
TPoint pt(Left+Width, Top+iTop);
if( m_iType==0 )
pt = Parent->ScreenToClient(pt);
m_SubMenu->Show( pt.x, pt.y );
// m_SubMenu->Repaint();
}
//---------------------------------------------------------------------------
void __fastcall TMenuPanel::Show( int X, int Y )
{
CalRect(X, Y);
u_AppEvent->OnMessage = DoHandleMessage;
Extctrls::TPanel::Show();
if( m_iType==0 )
SetCapture(Handle);
// Repaint();
Update();
}
//---------------------------------------------------------------------------
void __fastcall TMenuPanel::CalRect(int X, int Y)
{
RECT rc;
if( m_iType==0 )
SystemParametersInfo( SPI_GETWORKAREA, 0, &rc, 0 );
else{
rc.left = Application->MainForm->Left;
rc.top = Application->MainForm->Top;
rc.right = rc.left + Application->MainForm->Width;
rc.bottom = rc.top + Application->MainForm->Height;
}
int maxHeight = rc.bottom - rc.top - 27,
wid = WIDTH_MIN,
hei = TOP_HEIGHT*2;
for( int i=0; i<m_Items->Count; i++ ){
CMenuItem *pItem = (CMenuItem *)(m_Items->Items[i]);
if( pItem->Break ){
hei += HEIGHT_BREAK;
}
else {
String strText = pItem->Caption;
strText += pItem->Hotkey;
TSize size = Canvas->TextExtent( strText );
int w = size.Width + OFFSET_X * 2 + OFFSET_SEL * 2 + 12,
h = size.Height + OFFSET_Y * 2;
if( m_iType!=0 )
w += IMG_WIDTH;
if( pItem->Hotkey.Length()>0 )
w += 30;
if( pItem->HasSubItem() )
w += TRI_WIDTH + 10;
if( w > WIDTH_MAX ) w = WIDTH_MAX;
if( wid < w ) wid = w;
if( m_ItemHeight<h ) m_ItemHeight = h;
hei += h;
}
if( hei >= maxHeight ){
int board = ( TOP_HEIGHT + u_imgUp->Height ) * 2;
// hei = (maxHeight - board) / m_ItemHeight * m_ItemHeight + board;
hei = maxHeight;
m_iUpState = STATE_DISABLE;
m_iDownState = STATE_NORMAL;
break;
}
}
Width = wid;
Height = hei;
TPoint point(X,Y);
point = Parent->ClientToScreen(point);
if( point.X + Width > rc.right ){
if( m_SupMenu )
point.X = m_SupMenu->Left - Width;
else
point.X = rc.right - Width - 2;
}
if( point.Y + Height > rc.bottom ){
point.Y = rc.bottom - Height - 2;
}
if( m_iType!=0 )
point = Parent->ScreenToClient(point);
Left = point.X;
Top = point.Y;
}
//---------------------------------------------------------------------------
void __fastcall TMenuPanel::DeleteMenuItem(int index)
{
if( CLEAR_ALL==index ){
ClearAll();
}
else if( index>=0 && index<m_Items->Count ){
((CMenuItem*)m_Items->Items[index])->ClearSubItems();
}
}
//---------------------------------------------------------------------------
void __fastcall TMenuPanel::CreateWnd()
{
Vcl::Extctrls::TPanel::CreateWnd();
Canvas->Font->Name = g_strTxtFontName;
Canvas->Font->Quality = TFontQuality::fqClearTypeNatural;
Canvas->Font->Size = g_szFont9;
// Canvas->Font->Color = CLR_TXT_NOR;
// Canvas->Font->Assign( Application->MainForm->Font );
}
//---------------------------------------------------------------------------
void __fastcall TMenuPanel::CreateParams(TCreateParams &Params)
{
TPanel::CreateParams(Params);
if( m_iType==0 )
Params.Style = WS_POPUP;
}
//---------------------------------------------------------------------------
void __fastcall TMenuPanel::CloseMenu()
{
if( m_iType!=0 && Parent )
PostMessage( Parent->Handle, UM_MENUCLOSE, NULL, NULL );
}
//---------------------------------------------------------------------------
void __fastcall TMenuPanel::WMEraseBkgnd(Winapi::Messages::TWMEraseBkgnd &Message)
{
TRect rect = GetClientRect();
TCanvas* tempCanvas = new TCanvas;
tempCanvas->Handle = Message.DC;
//绘制底色
tempCanvas->Brush->Color = CLR_BKGRND_NOR;
tempCanvas->FillRect( rect );
//绘制外边框
tempCanvas->Brush->Color = CLR_BORDER;
tempCanvas->FrameRect( rect );
tempCanvas->Pixels[0][0] = CLR_BOARD_FILL;
tempCanvas->Pixels[Width][0] = CLR_BOARD_FILL;
tempCanvas->Pixels[Width][Height] = CLR_BOARD_FILL;
tempCanvas->Pixels[0][Height] = CLR_BOARD_FILL;
delete tempCanvas;
Message.Result = true;
}
//---------------------------------------------------------------------------
void __fastcall TMenuPanel::Paint(void)
{
int t = TOP_HEIGHT,
b = Height - TOP_HEIGHT,
h;
if( m_iUpState!=STATE_NONE ){ //绘制上翻箭头
h = u_imgUp->Height;
TRect rect( OFFSET_SEL, 0, Width-OFFSET_SEL, t+h );
DrawUpDown( Canvas, rect, true );
t += h;
b -= h;
}
bool bDisableDown = true;
for( int i=m_iFirst; i<m_Items->Count; i++ ){
CMenuItem *pItem = (CMenuItem*)m_Items->Items[i];
if( pItem->Break )
h = HEIGHT_BREAK;
else
h = m_ItemHeight;
if( t+h > b ){
bDisableDown = false;
break;
}
TRect rect( OFFSET_SEL, t, Width-OFFSET_SEL, t+h );
if( pItem->OnDrawItem )
pItem->OnDrawItem( pItem, Canvas, rect );
t += h;
}
//绘制竖线
if( t<b && IsDrawImg() ){
int X = OFFSET_SEL + IMG_WIDTH - 6,
Y = t;
Canvas->Pen->Color = CLR_BREAK;
Canvas->MoveTo( X, Y );
Y = b;
Canvas->LineTo( X, Y );
}
if( m_iDownState!=STATE_NONE ){ //绘制向下箭头
if( bDisableDown )
m_iDownState = STATE_DISABLE;
h = u_imgDown->Height;
TRect rect( OFFSET_SEL, b, Width-OFFSET_SEL, Height );
DrawUpDown( Canvas, rect, false );
}
}
//---------------------------------------------------------------------------
void __fastcall TMenuPanel::WMMouseMove(TWMMouse &Message)
{
if( !Visible )
return;
TShiftState Shift(Message.Keys);
int t = TOP_HEIGHT,
b = Height - TOP_HEIGHT,
h;
int iLastSel = m_iSelected;
if( m_iUpState!=STATE_NONE ){ //绘制上翻箭头
h = u_imgUp->Height;
bool bRedraw = false;
if( m_iUpState!=STATE_DISABLE ){
if( Message.YPos > 0 && Message.YPos < t+h
&& (Message.XPos >= 0 && Message.XPos <= Width ) ){
if( Shift.Empty() && m_iUpState!=STATE_HOVER ){
m_iUpState = STATE_HOVER;
bRedraw = true;
}
}
else{
if( m_iUpState!=STATE_NORMAL ){
m_iUpState = STATE_NORMAL;
bRedraw = true;
SAFE_DELETE(u_pTimer);
}
}
if( bRedraw ){
TRect rect( OFFSET_SEL, 0, Width-OFFSET_SEL, t+h );
DrawUpDown( Canvas, rect, true );
}
}
t += h;
b -= h;
}
for( int i=m_iFirst; i<m_Items->Count; i++ ) {
CMenuItem *pItem = (CMenuItem*)m_Items->Items[i];
if( pItem->Break )
h = HEIGHT_BREAK;
else
h= m_ItemHeight;
if( t+h<=b ){
if( !pItem->Break ){
if( Message.YPos > t && Message.YPos < t+h
&& (Message.XPos >= 0 && Message.XPos <= Width ) ){
if( !pItem->Selected ){
SAFE_DELETE(m_SubMenu) //子菜单
if( pItem->Enabled ){
pItem->Selected = true;
m_iSelected = i;
TRect rect( OFFSET_SEL, t, Width-OFFSET_SEL, t+h );
if( pItem->OnDrawItem )
pItem->OnDrawItem( pItem, Canvas, rect );
if( pItem->HasSubItem() )
ShowSubMenu(pItem, t);
}
else{
m_iSelected = -1;
}
}
}
else if( iLastSel==i ){
pItem->Selected = false;
TRect rect( OFFSET_SEL, t, Width-OFFSET_SEL, t+h );
if( pItem->OnDrawItem )
pItem->OnDrawItem( pItem, Canvas, rect );
if( m_iSelected==i )
m_iSelected = -1;
}
}
t += h;
}
else{
t = b;
break;
}
}
if( m_iDownState!=STATE_NONE ){ //绘制下翻箭头
h = u_imgUp->Height + TOP_HEIGHT;
bool bRedraw = false;
if( m_iDownState!=STATE_DISABLE ){
if( Message.YPos > t && Message.YPos < t+h
&& (Message.XPos >= 0 && Message.XPos <= Width ) ){
if( Shift.Empty() && m_iDownState!=STATE_HOVER ){
m_iDownState = STATE_HOVER;
bRedraw = true;
}
}
else{
if( m_iDownState!=STATE_NORMAL ){
m_iDownState = STATE_NORMAL;
bRedraw = true;
SAFE_DELETE(u_pTimer);
}
}
if( bRedraw ){
TRect rect( OFFSET_SEL, t, Width-OFFSET_SEL, t+h );
DrawUpDown( Canvas, rect, false );
}
}
}
if( !m_SubMenu && u_AppEvent->OnMessage!=DoHandleMessage ) {
u_AppEvent->OnMessage = DoHandleMessage;
if( m_iType==0 && GetCapture()!=Handle){
SetCapture( Handle );
}
}
}
//---------------------------------------------------------------------------
void __fastcall TMenuPanel::CMMouseLeave(TMessage &Message)
{
SAFE_DELETE( u_pTimer );
if( !Visible || m_SubMenu ) return;
int t = TOP_HEIGHT,
b = Height - TOP_HEIGHT,
h;
if( m_iUpState!=STATE_NONE ){ //绘制上翻箭头
h = u_imgUp->Height;
if( m_iUpState==STATE_HOVER || m_iUpState==STATE_DOWN ){
m_iUpState = STATE_NORMAL;
TRect rect( OFFSET_SEL, 0, Width-OFFSET_SEL, t+h );
DrawUpDown( Canvas, rect, true );
return;
}
t += h;
b -= h;
}
for( int i=m_iFirst; i<m_Items->Count; i++ ){
CMenuItem *pItem = (CMenuItem*)m_Items->Items[i];
if( pItem->Break )
h = HEIGHT_BREAK;
else
h = m_ItemHeight;
if( t+h<=b ){
if( pItem->Selected ){
pItem->Selected = false;
if( m_iSelected==i ){
m_iSelected = -1;
}
TRect rect( OFFSET_SEL, t, Width-OFFSET_SEL, t+h );
if( pItem->OnDrawItem )
pItem->OnDrawItem( pItem, Canvas, rect );
}
t += h;
}
else{
t = b;
break;
}
}
if( m_iDownState!=STATE_NONE ){ //绘制下翻箭头
h = u_imgUp->Height + TOP_HEIGHT;
bool bRedraw = false;
if( m_iDownState==STATE_HOVER || m_iDownState==STATE_DOWN ){
m_iDownState = STATE_NORMAL;
TRect rect( OFFSET_SEL, t, Width-OFFSET_SEL, t+h );
DrawUpDown( Canvas, rect, false );
}
}
}
//---------------------------------------------------------------------------
void __fastcall TMenuPanel::MouseDown(System::Uitypes::TMouseButton Button,
System::Classes::TShiftState Shift, int X, int Y)
{
if( !Visible )
return;
if( m_iSelected<0 ){
if( Button==mbLeft && m_iUpState!=STATE_NONE && X>0 && X<Width ){
int h = TOP_HEIGHT+u_imgUp->Height;
bool bRedraw = false;
if( m_iUpState==STATE_HOVER && Y>0 && Y<h ){ //向上翻动
m_iUpState = STATE_DOWN;
m_iFirst--;
if( ((CMenuItem*)m_Items->Items[m_iFirst])->Break )
m_iFirst--;
if( m_iDownState==STATE_DISABLE )
m_iDownState = STATE_NORMAL;
if( m_iFirst==0 )
m_iUpState = STATE_DISABLE;
bRedraw = true;
}
else if( m_iDownState==STATE_HOVER && Y<Height && Y>Height - h ){ //向下翻动
m_iDownState = STATE_DOWN;
m_iFirst++;
if( ((CMenuItem*)m_Items->Items[m_iFirst])->Break )
m_iFirst++;
if( m_iUpState==STATE_DISABLE ){
m_iUpState = STATE_NORMAL;
}
bRedraw = true;
}
if( bRedraw ){
SAFE_DELETE( u_pTimer );
u_pTimer = new TTimer(this);
u_pTimer->OnTimer = TimerProc;
u_pTimer->Tag = m_iUpState==STATE_DOWN ? -1 : 1;
u_pTimer->Interval = 500;
u_pTimer->Enabled = true;
InvalidateRgn( Handle, NULL, false );
}
}
return;
}
CMenuItem *pItemSel = (CMenuItem*)m_Items->Items[m_iSelected];
if( pItemSel->OnClick!=NULL &&
!(pItemSel->HasSubItem()) &&
!(pItemSel->Break) &&
pItemSel->Enabled )
{
HideAll();
pItemSel->OnClick((TObject*)pItemSel->MenuID);
}
}
//---------------------------------------------------------------------------
void __fastcall TMenuPanel::MouseUp(System::Uitypes::TMouseButton Button,
System::Classes::TShiftState Shift, int X, int Y)
{
SAFE_DELETE( u_pTimer );
if( !Visible )
return;
if( m_iSelected<0 ){
int h = TOP_HEIGHT+u_imgUp->Height;
if( m_iUpState==STATE_DOWN ){
if( X>0 && X<Width && Y>0 && Y<h )
m_iUpState = STATE_HOVER;
else
m_iUpState = STATE_NORMAL;
TRect rect( OFFSET_SEL, 0, Width-OFFSET_SEL, h );
DrawUpDown( Canvas, rect, true );
}
else if( m_iDownState==STATE_DOWN ){
if( X>0 && X<Width && Y<Height && Y>Height-h )
m_iDownState = STATE_HOVER;
else
m_iDownState = STATE_NORMAL;
TRect rect( OFFSET_SEL, Height-h, Width-OFFSET_SEL, Height );
DrawUpDown( Canvas, rect, false );
}
}
}
//---------------------------------------------------------------------------
void __fastcall TMenuPanel::DoHandleMessage(MSG &Msg, bool &Handled)
{
if( Visible ){
if( Msg.message==WM_LBUTTONDOWN || Msg.message==WM_RBUTTONDOWN
|| Msg.message==WM_NCLBUTTONDOWN || Msg.message==WM_NCRBUTTONDOWN ){
TMenuPanel* pMenu = (TMenuPanel*)this;
while( pMenu ){
TPoint ptCusor = pMenu->ScreenToClient(TPoint(Msg.pt.x, Msg.pt.y));
if( PtInRect( TRect(0, 0, pMenu->Width, pMenu->Height), ptCusor ) )
return;
pMenu = (TMenuPanel*)pMenu->m_SupMenu;
}
m_iSelected = -1;
HideAll();
}
else if( m_iType==0 && Msg.message==WM_MOUSEMOVE && Msg.wParam==0 ){
TPoint ptCusor = ScreenToClient(TPoint(Msg.pt.x, Msg.pt.y));
if( PtInRect( TRect(0, 0, Width, Height), ptCusor ) )
return;
TMenuPanel* pSup = (TMenuPanel*)m_SupMenu;
while( pSup ){
ptCusor = pSup->ScreenToClient(TPoint(Msg.pt.x, Msg.pt.y));
if( PtInRect( TRect(0, 0, pSup->Width, pSup->Height), ptCusor ) ){
PostMessage( pSup->Handle, WM_MOUSEMOVE, 0, MAKELONG(ptCusor.x, ptCusor.y) );
return;
}
pSup = (TMenuPanel*)pSup->m_SupMenu;
}
}
}
}
//---------------------------------------------------------------------------
void __fastcall TMenuPanel::HideAll()
{
Hide();
u_AppEvent->OnMessage = NULL;
SAFE_DELETE(u_pTimer);
if( m_iType==0 )
ReleaseCapture();
TMenuPanel* pSup = (TMenuPanel*)m_SupMenu;
while( pSup ){
pSup->Hide();
pSup = (TMenuPanel*)pSup->m_SupMenu;
}
CloseMenu();
}//---------------------------------------------------------------------------
void __fastcall TMenuPanel::DrawItem( TObject *Sender, TCanvas* ACanvas, const TRect &ARect )
{
CMenuItem *pItem = (CMenuItem *)Sender;
bool bIsDrawImg = IsDrawImg();
bool bIsDrawDir = pItem->IsDrawDir();
//绘制底色
ACanvas->Brush->Color = pItem->Selected ? CLR_BKGRND_HOT : CLR_BKGRND_NOR;
ACanvas->FillRect( ARect );
int X, Y;
//绘制选中框
if( pItem->Selected ){
ACanvas->Brush->Color = CLR_BORDER_HOT;
ACanvas->FrameRect( ARect );
}//绘制竖线
else if( bIsDrawImg ) {
X = ARect.Left + IMG_WIDTH - 6;
Y = ARect.Top;
ACanvas->Pen->Color = CLR_BREAK;
ACanvas->MoveTo( X, Y );
Y = ARect.Top + ARect.Height();
ACanvas->LineTo( X, Y );
}
//绘制间隔线
if( pItem->Break ){
if( bIsDrawImg ) X = ARect.Left + IMG_WIDTH + OFFSET_X + 2;
else X = ARect.Left + OFFSET_X + 2;
Y = ARect.Top + ( ARect.Bottom - ARect.Top )/2;
ACanvas->Pen->Color = CLR_BREAK;
ACanvas->MoveTo( X, Y );
X = ARect.Left + ARect.Width()-2;
ACanvas->LineTo( X, Y );
return;
}
//输出图标
if( bIsDrawImg && pItem->Icon ){
TPngImage* pIcon = pItem->Icon;
int w = pIcon->Width/2,
h = pIcon->Height,
l = pItem->Enabled ? 0 : w;
X = ARect.Left + ( IMG_WIDTH - pIcon->Width / 2 ) / 2;
Y = ARect.Top + ( ARect.Height() - pIcon->Height ) / 2;
HRGN rgnClip;
rgnClip = ::CreateRectRgn( X, Y, X+w, Y+h );
::SelectClipRgn( ACanvas->Handle, rgnClip );
ACanvas->Draw( X-l, Y, pIcon );
::SelectClipRgn( ACanvas->Handle, NULL );
::DeleteObject(rgnClip);
}
//输出Caption
ACanvas->Brush->Style = bsClear;
ACanvas->Font->Color = pItem->Enabled ? CLR_TXT_NOR : CLR_TXT_DISABLE;
if( bIsDrawImg ) X = ARect.Left + IMG_WIDTH + OFFSET_X;
else X = ARect.Left + OFFSET_X*2;
Y = ARect.Top + OFFSET_Y;
//---------------------
String strText = pItem->Caption;
int wHotKey = ACanvas->TextWidth( pItem->Hotkey );
int nWidth = ARect.Width() - TRI_WIDTH - IMG_WIDTH - 2*OFFSET_X - wHotKey;
if( bIsDrawDir ) strText = CutDirString(ACanvas, strText, nWidth);
ACanvas->TextOut( X, Y, strText );
//输出Hotkey
if( wHotKey>0 ){
X = ARect.Left + ARect.Width() - TRI_WIDTH - OFFSET_X - wHotKey;
ACanvas->TextOut( X, Y, pItem->Hotkey );
}
//输出子菜单提示
if( pItem->HasSubItem() ){
int w = u_imgSubMenu->Width/2,
h = u_imgSubMenu->Height,
l = pItem->Selected ? w : 0;
X = ARect.Left + ARect.Width() - TRI_WIDTH;
Y = ARect.Top + (ARect.Height() - h) / 2;
HRGN rgnClip;
rgnClip = ::CreateRectRgn( X, Y, X+w, Y+h );
::SelectClipRgn( ACanvas->Handle, rgnClip );
ACanvas->Draw( X-l, Y, u_imgSubMenu );
::SelectClipRgn( ACanvas->Handle, NULL );
::DeleteObject(rgnClip);
}
}
//---------------------------------------------------------------------------
void __fastcall TMenuPanel::DrawUpDown( TCanvas* ACanvas, const TRect &ARect, bool bUp )
{
int s = bUp ? m_iUpState : m_iDownState,
w = u_imgUp->Width/4,
h = u_imgUp->Height,
l = w * s;
int X = ARect.Left + ( ARect.Width() - w ) / 2,
Y = ARect.Top + (ARect.Height() - h) / 2 + ( bUp ? 1 : 2 );
HRGN rgnClip;
rgnClip = ::CreateRectRgn( X, Y, X+w, Y+h );
::SelectClipRgn( ACanvas->Handle, rgnClip );
ACanvas->Draw( X-l, Y, bUp ? u_imgUp : u_imgDown );
::SelectClipRgn( ACanvas->Handle, NULL );
::DeleteObject(rgnClip);
//绘制上线或下线
X = ARect.left + 2;
Y = bUp ? ARect.bottom - 1 : ARect.top;
ACanvas->Pen->Color = CLR_BREAK;
ACanvas->MoveTo( X, Y );
X = ARect.right - 2;
ACanvas->LineTo( X, Y );
}
//---------------------------------------------------------------------------
void __fastcall TMenuPanel::TimerProc(TObject* Sender)
{
if( u_pTimer && u_pTimer->Enabled ){
int direct = u_pTimer->Tag;
bool bRedraw = false,
bStop = true;
if( direct<0 && m_iUpState==STATE_DOWN ){
m_iFirst--;
if( ((CMenuItem*)m_Items->Items[m_iFirst])->Break )
m_iFirst--;
if( m_iFirst==0 )
m_iUpState = STATE_DISABLE;
else
bStop = false;
bRedraw = true;
}
else if( direct>0 && m_iDownState==STATE_DOWN ){
m_iFirst++;
if( ((CMenuItem*)m_Items->Items[m_iFirst])->Break )
m_iFirst++;
bStop = false;
bRedraw = true;
}
if( bRedraw )
InvalidateRgn( Handle, NULL, false );
if( bStop ){
SAFE_DELETE(u_pTimer);
// delete u_pTimer;
// u_pTimer = NULL;
}
else if( u_pTimer->Interval>200 ){
u_pTimer->Interval = 200;
}
}
}
//-----------------------------------------------------------------------------