1108 lines
26 KiB
C++
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;
|
|
}
|
|
}
|
|
}
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|