DELPHI의 이상한 메뉴의 탄생
번역자: Li Junyu 이메일: [email protected],[email protected]
사용자 정의 메뉴, 텍스트, 라인 / Delphi 4, 5
사용자 정의 메뉴, 텍스트, 라인/Delphi 4, 5
화려한 메뉴 등
이색 메뉴 등
사용자 정의 메뉴, 회전된 텍스트 및 특수 줄
맞춤형 메뉴, 회전된 텍스트, 특수 라인
Delphi 4 이전에는 메뉴를 사용자 정의(비트맵 추가, 글꼴 변경 등)하기가 어려웠습니다. 왜냐하면 Windows에서 구현되었음에도 불구하고 소유자 그리기(예: 사용자 정의 그리기)가 Delphi 4 이후로 TMainMenu 클래스에 의해 노출되지 않았기 때문입니다. 그러나 이 상황은 해결되었으며 메뉴를 사용하여 원하는 대로 할 수 있습니다.
Delphi 4 이전에는 Windows에서 실행되지만 소유자 그리기 이벤트(즉, 사용자 정의 그리기 이벤트)가 나타나지 않기 때문에 메뉴를 사용자 정의(BMP 이미지 추가, 글꼴 변경 등)하는 것이 어려웠습니다. TMainMenu 클래스. 델파이 4부터
이러한 상황은 바뀌었고 이제 메뉴를 사용자 정의할 수 있는 기능이 생겼습니다.
이 글에서는 Delphi 애플리케이션의 메뉴 모양을 사용자 정의하는 데 사용할 수 있는 몇 가지 기술을 중점적으로 설명하고, 재미를 위해 텍스트 배치, 메뉴 크기 조정, 글꼴 할당, 비트맵 및 모양 사용에 대해 설명합니다. 또한 회전된 텍스트와 사용자 정의 라인을 생성하는 기술도 제공합니다. 이 기사에서 설명하는 모든 기술은 다운로드할 수 있는 프로젝트에 설명되어 있습니다.
이 기사에서는 DELPHI 애플리케이션에서 메뉴의 모양을 사용자 정의하는 데 사용할 수 있는 몇 가지 기술에 중점을 두고 텍스트 배치, 메뉴 크기 조정, 글꼴 설정, BMP 파일 및 메뉴의 표시 효과 개선 사항을 다룹니다. . 재미를 위해 이 기사에서는 텍스트와 사용자 정의 선을 회전하는 기술을 자세히 설명합니다. 이 기사에서 논의된 모든 기술은 프로젝트 파일에서 디버깅되었으며 온라인으로 다운로드할 수 있습니다.
사용자 정의 글꼴 및 크기
글꼴 및 크기 설정
사용자 정의 메뉴를 생성하려면 메뉴 구성 요소인 TMainMenu 또는 TPopupMenu의 OwnerDraw 속성을 True로 설정하고 해당 OnDrawItem 및 OnMeasureItem 이벤트에 대한 이벤트 핸들러를 제공합니다. 예를 들어 OnMeasureItem 이벤트 핸들러는 다음과 같이 선언됩니다.
사용자 정의 메뉴를 만들려면 TmainMenu 또는 TpopupMenu 구성 요소의 OwnerDraw 속성을 TRUE로 설정하고 OnDrawItem 및 OnMeasureItem 이벤트 프로시저를 만듭니다. 예를 들어 OnMeasureItem 이벤트 프로시저는 다음과 같이 선언될 수 있습니다.
절차 TForm1.Option1MeasureItem(Sender: TObject;
ACanvas: TCanvas; var 너비, 높이: 정수);
메뉴 항목의 크기를 조정하려면 Width 및 Height 변수를 설정하세요. OnDrawItem 이벤트 핸들러는 메뉴를 그리고 Times New Roman 글꼴을 사용하여 메뉴 옵션을 그리는 곳입니다. , 예를 들어 다음과 같이 해야 합니다.
위 이벤트 프로시저에서 메뉴 항목의 Width 및 Height 변수를 적절한 크기로 설정합니다. 모든 주요 항목은 OnDrawItem 이벤트에 의해 트리거됩니다. 여기에서 메뉴를 다시 그리고 특별한 설정을 수행합니다. 예를 들어 Times New Roman 글꼴로 메뉴 항목을 다시 그리려면 다음을 수행합니다.
절차 TForm1.Times1DrawItem(Sender: TObject;
ACanvas: TCanvas; ARect: TRect 선택: 부울;
시작하다
ACanvas.Font.Name := '타임즈 뉴 로만';
ACanvas.TextOut(ARect.Left+1, ARect.Top+1,
(TMenuItem으로 보낸 사람).Caption);
끝;
그러나 이 코드를 실행하면 메뉴 캡션이 메뉴의 왼쪽 테두리에 정렬되어 그려집니다. 이는 일반적으로 메뉴에 비트맵과 확인 표시를 넣을 수 있는 공간이 있습니다. 그림 1에 표시된 것과 같은 코드를 사용하여 이 체크 표시에 필요한 공간을 계산해야 합니다. 그림 2는 결과 메뉴를 보여줍니다.
그러나 이 코드에는 결함이 있습니다. 이 코드를 실행하면 메뉴 항목의 캡션이 메뉴 항목의 왼쪽에 정렬됩니다. 이는 Windows의 기본 동작이 아닙니다. 일반적으로 메뉴 왼쪽에는 BMP 이미지와 선택 항목을 위한 공간이 있습니다. 표시. 따라서 그림 1과 같이 코드를 사용하여 선택 플래그를 배치하는 데 필요한 공간을 계산해야 합니다. 그림 2는 실제 메뉴를 보여줍니다.
절차 TForm1.Times2DrawItem(Sender: TObject;
ACanvas: TCanvas; ARect: TRect 선택: 부울;
var
dwCheck : 정수;
메뉴캡션: 문자열;
시작하다
// 체크표시 크기를 가져옵니다.
선택 로고에 필요한 픽셀 수를 가져옵니다.
dwCheck := GetSystemMetrics(SM_CXMENUCHECK);
// 왼쪽 위치를 조정합니다.
왼쪽 위치 조정
ARect.Left := ARect.Left + LoWord(dwCheck) + 1;
MenuCaption := (TMenuItem으로 보낸 사람).Caption;
// 글꼴 이름은 메뉴 캡션입니다.
ACanvas.Font.Name := '타임즈 뉴 로만';
// 텍스트를 그립니다.
텍스트 그리기
DrawText(ACanvas.Handle, PChar(메뉴캡션),
길이(메뉴캡션), ARect, 0);
끝;
그림 1: 이 OnDrawItem 이벤트 핸들러는 메뉴 항목 텍스트를 올바르게 배치합니다.
[번역자는 모든 그림을 생략했습니다. 아래도 동일]
그림 2: 사용자 정의 글꼴로 그려진 메뉴.
메뉴에 표시할 텍스트가 너무 크면 Windows에서 텍스트를 맞게 잘라냅니다. 따라서 모든 텍스트를 그릴 수 있도록 메뉴 항목 크기를 설정해야 합니다. 이것이 그림 3에 표시된 OnMeasureItem 이벤트 핸들러의 역할입니다. .
텍스트가 너무 길면 Windows에서 텍스트에 맞게 자동으로 자릅니다. 따라서 모든 텍스트가 표시될 수 있도록 메뉴 크기를 조정해야 합니다. 그림 3에 나와 있는 OnMeasureItem 이벤트에서도 마찬가지입니다.
절차 TForm1.Times2MeasureItem(Sender: TObject;
ACanvas: TCanvas; var 너비, 높이: 정수);
시작하다
ACanvas.Font.Name := '타임즈 뉴 로만';
ACanvas.Font.Style := [];
// 너비는 메뉴 체크 공간입니다.
이 길이는 메뉴 선택 표시의 길이입니다.
// 항목 텍스트의 너비를 더합니다.
메뉴 항목의 길이에 더해
너비 := GetSystemMetrics(SM_CXMENUCHECK) +
ACanvas.TextWidth((TMenuItem으로 보낸 사람).Caption) + 2;
높이 := ACanvas.TextHeight(
(TMenuItem으로 보낸 사람).Caption) + 2;
끝;
그림 3: 이 OnMeasureItem 이벤트 핸들러는 항목이 해당 메뉴에 맞는지 확인합니다.
사용자 정의 모양 및 비트맵
그래픽 및 비트맵 설정
비트맵이나 기타 모양을 포함하여 메뉴 항목을 사용자 정의할 수도 있습니다. 비트맵 파일을 TMenuItem.Bitmap 속성에 할당하면 됩니다. 디자인 타임에 Object Inspector를 사용하거나 런타임에 코드를 사용하면 됩니다. 메뉴 항목의 캡션으로 그림 4에 표시된 OnDrawItem 이벤트 핸들러를 사용할 수 있습니다. 그림 5는 결과를 보여줍니다.
비트맵 및 기타 그래픽을 사용하여 메뉴를 설정할 수 있습니다. 비트맵을 추가하려면 디자인 타임에 Object Inspector의 TmenuItem의 Bitmap 속성에 BMP 파일을 할당하거나 런타임에 코드를 사용하는 것도 가능합니다. 메뉴 제목을 색상이 지정된 직사각형으로 바꾸려면 그림 4와 같이 OnDrawItem 이벤트를 사용할 수 있습니다. 결과는 그림 5에 나와 있습니다.
절차 TForm1.ColorDrawItem(Sender: TObject;
ACanvas: TCanvas; ARect: TRect 선택: 부울;
var
dwCheck : 정수;
메뉴색상: TColor;
시작하다
// 체크표시 크기를 가져옵니다.
dwCheck := GetSystemMetrics(SM_CXMENUCHECK);
ARect.Left := ARect.Left + LoWord(dwCheck);
// 메뉴 항목의 캡션을 색상으로 변환합니다.
메뉴 항목 제목을 색상으로 변환
메뉴색상 :=
StringToColor((TMenuItem으로 보낸 사람).Caption);
// 캔버스 브러시 색상을 변경합니다.
캔버스의 브러시 색상 변경
ACanvas.Brush.Color := MenuColor;
// 항목이 선택되면 사각형을 그립니다.
메뉴 항목이 선택되면 직사각형을 그립니다.
// 테두리를 그립니다.
테두리 그리기
선택한 경우
ACanvas.Pen.Style := psSolid
또 다른
ACanvas.Pen.Style := psClear;
ACanvas.Rectangle(ARect.Left, ARect.Top,
ARect.오른쪽, ARect.하단);
끝;
그림 4: OnDrawItem 이벤트를 사용하여 메뉴 항목에 색상이 지정된 직사각형을 그립니다.
그림 5: 색상이 지정된 직사각형이 항목으로 포함된 메뉴.
단 한 가지 문제가 있습니다. Delphi 5를 사용하는 경우 메뉴의 AutoHotkeys 속성을 maManual로 설정해야 합니다. 이를 기본값인 maAutomatic으로 두면 Delphi는 캡션에 앰퍼샌드 문자(&)를 추가하므로 이 속성이 깨집니다. 또 다른 해결책은 StripHotKey 함수를 사용하여 앰퍼샌드를 제거하는 것입니다.
더 널리 사용되는 접근 방식은 Delphi 5를 사용하는 경우 메뉴의 AutoHotkeys 속성을 maManual로 설정해야 한다는 것입니다. 이 작업을 수행하지 않고 기본값인 maAutomatic을 그대로 두면 Delphi는 자동으로 제목에 앰퍼샌드를 추가하므로 코드가 깨집니다. 또 다른 해결책은 StripHotKey 함수를 사용하여 앰퍼샌드를 제거하는 것입니다.
OnDrawItem 및 OnMeasureItem 이벤트를 사용하는 또 다른 방법은 메뉴에 텍스트를 세로로 쓰는 것입니다(그림 7 참조). 이렇게 하려면 회전된 글꼴을 만들어야 합니다. 이는 Windows API 함수 CreateFont 또는 CreateLogFont를 통해서만 가능합니다. 이 기사 뒷부분의 "회전된 텍스트" 팁) 그런 다음 메뉴 항목이 그려질 때마다 이 이벤트가 시작됩니다. 20개의 항목이 있으면 20번 그려집니다. 더 빠르게 하기 위해 메뉴 항목이 선택된 경우에만 세로 텍스트가 그려집니다(한 번에 하나의 메뉴 항목만 선택되므로). 그림 6은 이것이 코드로 구현되는 방법을 보여줍니다. , 그림 7은 런타임 결과를 보여줍니다.
OnDrawItem 및 OnMeasureItem 이벤트의 또 다른 용도는 메뉴 옆에 세로 텍스트를 쓰는 것입니다(예: 그림 7 참조). 이렇게 하려면 회전된 글꼴을 만들어야 합니다. 유일한 방법은 Windows API의 CreateFont 또는 CreateLogFont 함수를 사용하는 것입니다(이 문서 뒷부분의 "회전된 텍스트" 기술 참조). 따라서 OnDrawItem 이벤트에서 다시 그려야 합니다. 이 이벤트는 메뉴 항목을 꺼낼 때 실행되므로 메뉴 항목이 20개라면 20번 실행됩니다. 속도를 높이기 위해 메뉴 항목을 선택할 때마다 세로 텍스트를 다시 그릴 수 있습니다(한 번에 하나의 메뉴 항목만 선택하더라도). 그림 6은 코드 실행 방법을 보여주고, 그림 7은 결과를 보여줍니다.
절차 TForm1.VerticalDrawItem(Sender: TObject;
ACanvas: TCanvas; ARect: TRect 선택: 부울;
var
lf : TLogFont;
OldFont:HFont;
clFore, clBack: LongInt;
직사각형: TRect;
dwCheck : LongInt;
메뉴 높이 : 정수;
시작하다
dwCheck := GetSystemMetrics(SM_CXMENUCHECK);
// 항목이 선택되면 이 작업이 한 번 수행됩니다.
메뉴 항목을 선택하면 실행됩니다.
선택한 경우 시작
// 회전된 글꼴을 만듭니다.
회전된 글꼴 만들기
FillChar(lf, SizeOf(lf), 0);
lf.lfHeight := -14;
lf.lfEscapement := 900;
lf.lf방향 := 900;
lf.lfWeight := Fw_Bold;
StrPCopy(lf.lfFaceName, 'Arial');
// 그릴 글꼴을 선택합니다.
그리려면 이 글꼴을 선택하세요.
OldFont := SelectObject(ACanvas.Handle,
CreateFontIndirect(lf));
// 전경색과 배경색을 변경합니다.
전경색과 배경색 변경
clFore := SetTextColor(ACanvas.Handle, clSilver);
clBack := SetBkColor(ACanvas.Handle, clBlack);
// 메뉴 높이를 구합니다.
메뉴 높이 얻기
MenuHeight := (ARect.Bottom-ARect.Top) *
((TMenuItem으로 보낸 사람).Parent는 TMenuItem으로).Count;
Rectang := Rect(-1, 0, dwCheck-1, MenuHeight);
// 텍스트를 그립니다.
텍스트 그리기
ExtTextOut(ACanvas.Handle, -1, MenuHeight, Eto_Clipped,
@Rectang, 'Made in Borland', 15, 없음);
// 원래 상태로 돌아갑니다.
원래 상태로 돌아가기
DeleteObject(SelectObject(ACanvas.Handle, OldFont));
SetTextColor(ACanvas.Handle, clFore);
SetBkColor(ACanvas.Handle, clBack);
끝;
// 실제 메뉴 텍스트를 그립니다.
실제 메뉴 항목 텍스트 그리기
ARect.Left := ARect.Left + LoWord(dwCheck) + 2;
DrawText(ACanvas.Handle,
PChar((TMenuItem으로 보낸 사람).캡션),
Length((TMenuItem으로 보낸 사람).Caption), ARect, 0);
끝;
그림 6: OnDrawItem을 사용하여 메뉴에 세로 텍스트를 그립니다.
그림 7: 세로 텍스트가 있는 메뉴.
한 가지 까다로운 세부 사항은 텍스트 그리기를 시작할 위치를 아는 것입니다. 텍스트는 메뉴의 마지막 항목 하단에서 시작되어야 합니다. 위치를 얻으려면 다음을 사용하여 메뉴 항목의 높이를 가져옵니다.
텍스트 그리기를 시작할 위치를 알아야 합니다. 메뉴의 마지막 항목 맨 아래에서 시작해야 합니다. 이 위치를 얻기 위해 다음과 같이 메뉴 항목의 높이를 얻습니다.
ARect.Top - ARect.Bottom
메뉴의 항목 수를 곱합니다.
메뉴 항목 수를 곱하면 다음과 같습니다.
(((TMenuItem으로 보낸 사람).Parent는 TMenuItem으로).Count)
회전된 텍스트
회전된 텍스트
Windows API를 사용하면 Delphi에서 어떤 각도로든 텍스트를 그릴 수 있습니다. 이를 위해서는 API 함수 CreateFont를 사용해야 합니다. 또는 CreateFontIndirect가 그림 8과 같이 선언됩니다.
Windows API를 사용하면 어떤 각도로든 텍스트를 그릴 수 있습니다. Delphi에서 이 작업을 수행하려면 CreateFont 또는 CreateFontIndirect 두 API 함수를 사용해야 합니다. 그림 8은 CreateFont가 선언되는 방법을 보여줍니다.
함수 CreateFont(
nHeight, // 글꼴의 논리적 높이입니다.
nWidth, // 논리적 평균 문자 너비입니다.
nEscapement, // 이스케이프먼트 각도.
nOrientation, // 기준선 방향 각도입니다.
fnWeight: Integer; // 글꼴의 가중치 하위 속성입니다.
fdwItalic, // 기울임꼴 속성 플래그입니다.
fdwUnderline, // 밑줄 속성 플래그.
fdwStrikeOut, // 삼진 속성 플래그.
fdwCharSet // 문자 세트 식별자.
fdwOutputPrecision, // 출력 정밀도.
fdwClipPrecision, // 클리핑 정밀도.
fdwQuality, // 출력 품질.
fdwPitchAndFamily: DWORD; // 피치 및 패밀리.
lpszFace: PChar // 서체 이름 문자열에 대한 포인터입니다.
): HFONT;
그림 8: CreateFont Windows API 함수에 대한 오브젝트 파스칼 선언.
이 함수에는 많은 매개변수가 있지만 일반적으로 텍스트의 하나 또는 두 개의 속성만 변경하려는 경우 대신 CreateFontIndirect 함수를 사용해야 합니다. 이 함수는 그림에 표시된 대로 TLogFont 유형의 레코드만 사용합니다. 9.
이 함수는 많은 매개변수를 사용하지만 일반적으로 텍스트의 속성을 한두 개만 변경하면 됩니다. 이 경우 대신 CreateFontIndirect 함수를 사용합니다. 그림 9에서 볼 수 있듯이 TlogFont의 레코드 유형 매개변수인 하나의 매개변수만 필요합니다.
tagLOGFONTA = 압축된 기록
lfHeight: Longint;
lfWidth: Longint;
lfEscapement: Longint;
lf방향: Longint;
lf무게: Longint;
lf기울임꼴: 바이트;
lfUnderline: 바이트;
lfStrikeOut: 바이트;
lfCharSet: 바이트;
lfOutPrecision: 바이트;
lfClipPrecision: 바이트;
lf품질: 바이트;
lfPitchAndFamily: 바이트;
lfFaceName: AnsiChar의 배열[0..LF_FACESIZE - 1];
끝;
TLogFontA = tagLOGFONTA;
TLogFont = TLogFontA;
그림 9: TLogFont 레코드.
이 레코드를 보면 해당 멤버가 CreateFont 함수의 매개 변수와 일치하는 것을 알 수 있습니다. 이 함수/레코드 조합을 사용하면 GetObject API 함수를 사용하여 레코드의 멤버를 알려진 글꼴로 채울 수 있고 원하는 멤버를 변경할 수 있다는 것입니다. 원하는 새 글꼴을 만듭니다.
이 레코드 유형을 자세히 살펴보면 해당 멤버가 CreateFont 함수의 매개 변수와 매우 유사하다는 것을 알 수 있습니다. 이 함수/레코드 조합을 사용하면 GetObject API 함수를 사용하여 이 레코드의 멤버 값을 알려진 글꼴로 채운 다음 변경하려는 멤버 값을 변경하여 새 글꼴을 생성할 수 있다는 이점이 있습니다.
회전된 텍스트를 그리려면 텍스트 각도를 10분의 1도 단위로 설정하는 lfEscapement 멤버만 변경해야 합니다. 따라서 텍스트를 45도로 그리려면 lfEscapement를 450으로 설정해야 합니다.
회전된 텍스트를 그리려면 글꼴 각도를 10분의 1도 단위로 설정하는 lfEscapement 멤버만 변경해야 합니다. 따라서 캐릭터를 45도 회전시키려면 다음을 설정해야 합니다.
lfEscapement는 450입니다.
기울임꼴, 밑줄 및 취소선 텍스트를 그리는 플래그는 있지만 굵은 텍스트를 그리는 플래그는 없습니다. 이는 0에서 1000 사이의 숫자인 lfWeight 멤버를 사용하여 수행됩니다. 400은 일반 텍스트이며 이보다 큰 값입니다. 굵은 텍스트를 그리고 그 아래의 값은 밝은 텍스트를 그립니다.
텍스트에 이탤릭체, 밑줄, 강조 표시를 하는 마커는 꽤 많지만 텍스트를 굵은 글씨로 표시하는 마커는 없습니다. 이는 lfWeight 멤버가 대신 사용되며 이 멤버의 값이 0에서 1000 사이이기 때문입니다. 400이 정상 값이고, 이보다 높으면 굵은 글씨로, 이보다 낮으면 얇아집니다.
그림 10의 코드는 20도 간격으로 0도에서 360도 범위의 각도로 텍스트를 그립니다. 이는 폼의 OnPaint 이벤트 처리기이므로 폼이 그려질 때마다 텍스트가 다시 그려집니다.
그림 10의 코드는 0도에서 360도까지 20도마다 문자를 그립니다. 이는 양식의 OnPaint 이벤트에서 트리거되므로 양식을 그릴 때마다 텍스트가 다시 그려집니다. 그 효과는 그림 11에서 확인할 수 있습니다.
절차 TForm1.FormPaint(Sender: TObject);
var
OldFont, NewFont: hFont;
로그폰트: TLogFont;
i : 정수;
시작하다
// 캔버스 글꼴 핸들을 가져옵니다.
양식 글꼴 개체에 대한 핸들을 가져옵니다.
OldFont := Canvas.Font.Handle;
나는 := 0;
// 투명 그리기.
투명도 속성 설정
SetBkMode(Canvas.Handle, Transparent);
// LogFont 구조를 정보로 채웁니다.
LogFont 구조에 정보를 입력하세요.
// 현재 글꼴에서.
현재 글꼴에서
GetObject(OldFont, Sizeof(LogFont), @LogFont);
// 각도 범위는 0에서 360까지입니다.
0도에서 360도까지
내가 < 3600인 동안 시작하세요
// 이스케이프먼트를 새로운 각도로 설정합니다.
텍스트 방향을 새로운 각도로 설정
LogFont.lfEscapement := i;
//새 글꼴을 만듭니다.
새 글꼴 만들기
NewFont := CreateFontIndirect(LogFont);
// 그릴 글꼴을 선택합니다.
출력할 글꼴 선택
SelectObject(Canvas.Handle, NewFont);
// 폼 중앙에 텍스트를 그립니다.
양식 중간에 텍스트 출력
TextOut(Canvas.Handle, ClientWidth div 2,
ClientHeight div 2, '회전된 텍스트', 21);
// 정리합니다.
분명한
DeleteObject(SelectObject(Canvas.Handle, OldFont));
// 각도를 20도씩 증가시킵니다.
20도마다 증가
Inc(i, 200);
끝;
끝;
그림 10: 20도 간격으로 회전된 텍스트를 그리는 코드.
그림 11: 360도 회전된 텍스트.
양식의 글꼴은 TrueType 글꼴인 Arial로 설정됩니다. 다른 종류의 글꼴은 텍스트 회전을 지원하지 않으며 TLogFont 구조를 채우려면 GetObject API 함수를 사용해야 합니다. 그림 12의 코드는 양식 글꼴에 대한 TLogFont 설정을 채우고 표시하는 방법을 보여줍니다.
이 양식의 글꼴은 TrueType 글꼴인 Arial로 설정되어 있습니다. 이 코드는 트루타입 글꼴에서만 실행되며 다른 글꼴은 텍스트 회전을 지원하지 않습니다. 현재 글꼴 설정을 얻고 TlogFont 구조를 채우려면 GetObject API 함수를 사용해야 합니다. 그림 12의 코드에서는 양식에 TlogFont 설정을 채우고 표시하는 방법을 볼 수 있습니다.
절차 TForm1.Info1Click(Sender: TObject);
var
로그폰트: TLogFont;
시작하다
// LogFont 구조를 정보로 채웁니다.
LogFont 구조의 멤버 값을 입력합니다.
// 현재 글꼴에서.
현재 글꼴에서
GetObject(Canvas.Font.Handle, Sizeof(LogFont), @LogFont);
// 글꼴 정보를 표시합니다.
글꼴 정보 표시
LogFont를 사용하면 ShowMessage(
'lfHeight: ' + IntToStr(lfHeight) + #13 +
'lfWidth: ' + IntToStr(lfWidth) + #13 +
'lfEscapement: '+IntToStr(lfEscapement) + #13 +
'lf방향: ' + IntToStr(lf방향) + #13 +
'lfWeight: ' + IntToStr(lfWeight) + #13 +
'lfItalic: ' + IntToStr(lfItalic) + #13 +
'lfUnderline: ' + IntToStr(lfUnderline) + #13 +
'lfStrikeOut: ' + IntToStr(lfStrikeOut) + #13 +
'lfCharSet: ' + IntToStr(lfCharSet) + #13 +
'lfOutPrecision: ' + IntToStr(lfOutPrecision) + #13 +
'lfClipPrecision: ' + IntToStr(lfClipPrecision) + #13 +
'lfQuality: ' + IntToStr(lfQuality) + #13 +
'lfPitchAndFamily: '+IntToStr(lfPitchAndFamily) + #13 +
'lfFaceName: ' + string(lfFaceName));
끝;
그림 12: 글꼴 속성 가져오기 및 표시.
TLogFont 구조에 설정이 있으면 남은 유일한 변경 사항은 lfEscapement를 원하는 각도로 설정하고 CreateFontIndirect를 사용하여 새 글꼴을 만드는 것입니다. 이 새 글꼴을 사용하기 전에 SelectObject를 사용하여 선택해야 합니다. 텍스트를 그리기 전에 이 새 글꼴을 캔버스 글꼴 핸들에 저장해야 합니다. 텍스트를 그린 후에는 이전 글꼴을 선택하고 새 글꼴을 삭제해야 합니다. 삭제되지 않으면 메모리 누수가 발생하며, 루틴이 여러 번 실행되면 Windows(특히 95/98)의 리소스가 부족해 충돌이 발생합니다.
TlogFont 구조를 설정하고 나면 남은 작업은 lfEscapement 값을 대상 값으로 변경하고 CreateFontIndirect를 사용하여 새 글꼴을 생성하는 것뿐입니다. 이 새 글꼴을 사용하기 전에 SelectObject를 사용하여 선택해야 합니다. 또 다른 방법은 텍스트를 그리기 전에 이 새 글꼴 개체의 핸들을 양식 캔버스의 글꼴 개체 핸들에 사용하는 것입니다. 텍스트를 그린 후에는 이전 글꼴을 선택하고 새 글꼴을 삭제해야 합니다. 새 글꼴을 제거하지 않으면 메모리 누수가 발생하고 -----프로그램을 여러 번 실행하면------ Windows(특히 95/98)에서는 리소스가 부족해지며,
충돌.
세련된 라인
인기 라인
선을 그릴 때 개별 픽셀은 일반적으로 중요하지 않으며 단순히 선 스타일을 설정하면 Windows에서 그려집니다. 그러나 때로는 Windows에서 제공하지 않는 선 스타일을 그려야 하는 경우도 있습니다. 그림 13에 정의된 LineDDA라는 Windows API 함수를 사용합니다.
선을 그릴 때 개별 픽셀은 일반적으로 중요하지 않습니다. 선 유형만 설정하면 선 그리기 작업은 Windows에 맡겨집니다. 그러나 때로는 Windows에서 제공하지 않는 특수한 선 유형을 사용하고 싶을 수도 있습니다. 이는 그림 13에 정의된 LineDDA라는 API 함수를 사용하여 달성할 수 있습니다.
함수 LineDDA(
nXStart, // 선 시작점의 x 좌표입니다.
X 좌표 시작점
nYStart, // 선 시작점의 y좌표입니다.
Y 좌표 시작점
nXEnd, // 선 끝점의 x 좌표.
X 좌표 끝점
YEnd : Integer; // 줄 끝점의 y좌표입니다.
Y 좌표 끝점
// 애플리케이션에서 정의한 콜백 함수의 주소입니다.
애플리케이션 정의 콜백 함수의 주소
lpLineFunc: TFNLineDDAProc;
lpData : LPARAM // 애플리케이션 정의 데이터의 주소입니다.
애플리케이션 정의 데이터의 주소
): BOOL;
그림 13: Windows API 함수 LineDDA에 대한 오브젝트 파스칼 선언.
처음 4개 매개변수는 선의 시작점과 끝점입니다. 다섯 번째 매개변수는 픽셀을 그려야 할 때마다 호출되는 콜백 함수입니다. 마지막 매개변수는 사용자 매개변수입니다. 콜백 함수에 전달됩니다. LParam(Win32에서는 Longint로 변환됨)이므로 함수에 모든 정수 또는 포인터를 전달할 수 있습니다.
처음 네 개의 매개변수는 선의 시작점과 끝점입니다. 다섯 번째 매개변수는 픽셀을 그릴 때마다 호출되는 콜백 함수입니다. 여기에 그리기 과정에 대해 쓸 수 있습니다. 마지막 매개변수는 사용자가 정의하며 콜백 함수에 전달될 수 있습니다. 이 함수에는 정수나 포인터를 전달할 수 있습니다.
Lparam 유형(WIN32에서는 Longint 유형으로 해석됨) 이 콜백 함수는 다음과 같은 형식을 사용해야 합니다.
프로시저 CallBackDDA(x, y: 정수;
UserParam: LParam);
여기서 x와 y는 그려진 점의 좌표이고 UserParam은 함수에 전달되는 매개 변수입니다. 이 함수는 stdcall로 선언되어야 하며 그림 14의 루틴은 비트맵 선을 그리고 그림 15는 그 결과를 보여줍니다.
여기서 X와 Y는 그려지는 좌표점이고 UserParam은 매개변수입니다. 이 함수는 stdcall로 하위 정의되어야 합니다. 그림 14의 프로그램은 BMP 라인을 그리고 그림 15는 결과를 표시합니다.
유형
TForm1 = 클래스(TForm)
ImageList1: TImageList;
절차 FormPaint(보내는 사람: TObject);
절차 FormResize(Sender: TObject);
끝;
var
Form1: TForm1;
절차 CallDDA(x, y: 정수; 형식: TForm1);
구현
{ $R *.DFM }
절차 CallDDA(x, y: 정수; 형식: TForm1);
시작하다
x mod 13 = 0이면
Form.ImageList1.Draw(Form.Canvas, x, y, 0);
끝;
절차 TForm1.FormPaint(Sender: TObject);
시작하다
LineDDA(0, 0, 클라이언트 너비, 클라이언트 높이,
@CallDDA, 정수(자체));
끝;
절차 TForm1.FormResize(Sender: TObject);
시작하다
무효화하다;
끝;
그림 14: 비트맵 선을 그리는 코드.
그림 15: 사용자 정의 라인이 있는 창.
이 루틴은 LineDDA를 호출하여 양식의 OnPaint 이벤트를 처리하므로 양식을 그려야 할 때마다 선을 다시 그립니다. 처리되는 또 다른 이벤트는 양식 클라이언트 영역을 무효화하는 OnResize이므로 누군가가 해당 선을 변경할 때 선을 다시 그려야 합니다. LineDDA 콜백 함수인 CallDDA는 호출될 때마다 ImageList에 저장된 비트맵을 그립니다. Self가 마지막 매개변수로 전달됩니다. 콜백 함수를 사용하여 인스턴스 데이터에 액세스할 수 있습니다.
이 프로그램은 LineDDA를 호출하여 양식의 OnPaint 이벤트를 처리하므로 양식이 그려질 때마다 선을 다시 그립니다. 또 다른 이벤트는 OnResize로, 누군가 크기를 변경할 때 선이 다시 그려지도록 양식의 클라이언트 영역을 무효화합니다. LineDDA 콜백 함수와 CallDDA는 매우 간단합니다. 13번 호출될 때마다 ImageList에 저장된 비트맵을 그립니다. 아마도 SELF가 콜백 함수의 마지막 매개변수로 전달되어 프로그램의 데이터에 액세스할 수 있다는 점을 눈치챘을 것입니다.
결론
결론적으로
Delphi 4의 TMainMenu에 소유자 드로잉이 노출된 이후로 메뉴를 확장하는 방법이 많이 있었습니다. 여기서 논의한 기술을 사용하면 사용자 정의 텍스트, 비트맵 및 색상으로 Delphi 애플리케이션의 메뉴를 쉽게 향상시킬 수 있습니다.
이제 소유자 드로잉이 Delphi 4의 TmainMenu에 나타났으므로 메뉴 기능을 확장할 수 있는 다양한 방법이 있습니다. 위에서 논의한 기술을 사용하면 사용자 정의 텍스트, 비트맵 및 색상으로 DELPHI 애플리케이션의 메뉴 기능을 쉽게 향상시킬 수 있습니다.