[TMemo Component] 현재 라인번호 알아내기
메모에서 현재 Caret이 위치하고 있는 줄이 몇 번째 줄인지를 리턴한다.
Label1.Caption := IntToStr(GetCurrLine(Memo1));
function GetCurrLine(Memo : TMemo) : integer;
begin
Result := Memo.Perform(EM_LINEFROMCHAR, Memo.SelStart, 0);
end;
[TMemo Component] 현재 컬럼번호 알아내기
메모에서 현재 Caret이 위치하고 있는 줄에서 몇 번째 컬럼인지를 리턴한다.
Label1.Caption := IntToStr(GetCurrCul(Memo1));
function GetCurrCul(Memo : TMemo)) : integer;
begin
Result := Memo.SelStart - Memo.Perform(EM_LINEINDEX, GetCurrLine(Memo), 0);
end;
[TMemo Component] Caret를 원하는 라인으로 이동하기
Caret을 원하는 위치로 이동시키는데 이때 넘겨주는 값이 라인의 한계를 벗어나면 그 안 범위로 위치시킨다.
만약 라인의 맨끝으로 이동시키고 싶다면 아주 큰값을 주면된다.
SetCurrLine(Memo1. 10);
procedure SetCurrLine(Memo : TMemo; Value : integer);
begin
if Value < 0 then Value := 0;
if Value > Memo.Lines.Count then Value := Memo.Lines.Count;
Memo.SelLength := 0;
Memo.SelStart := Memo.Perform(EM_LINEINDEX, Value, 0);
end;
[TMemo Component] Caret을 원하는 컬럼으로 이동하기
SetCurrCul(Memo1. 10);
procedure SetCurrCul(Memo : TMemo; Value : integer);
var
CurrLine : integer;
begin
CurrLine := GetCurrLine(Memo);
if Value < 0 then Value := 0;
if (Value > Length(Memo.Lines[CurrLine])) then
Value := Length(Memo.Lines[CurrLine]);
Memo.SelLength := 0;
Memo.SelStart := Memo.Perform(EM_LINEINDEX, CurrLine, 0) + Value;
end;
[TMemo Component] Text가 쓰여지는 영역 알아내기
현재 Text가 쓰여지는 영역을 TRect형으로 리턴한다.
즉 글자의 높이가 10이고 메모의 높이가 25라면 2라인만이 그려지게 된다.
따라서 글자가 그려지는 정확한 영역을 알아내기 위해서는 아래 함수를 사용한다.
Rect := GetTextRect(Memo1);
function GetTextRect(Memo : TMemo) : TRect;
var
lParam : TRect;
begin
Memo.Perform(EM_GETRECT, 0, Integer(@lParam));
Result := lParam;
end;
[TMemo Component] 메모에서 현재 보이는 라인수 알아내기
Label1.Caption := IntToStr(GetVisibleLine(Memo1));
function GetVisibleLine(Memo : TMemo) : integer;
var
Metric : TTextMetric;
DC : hDC;
begin
DC := GetWindowDC(Memo.Handle);
GetTextMetrics(DC, Metric);
Result := (GetTextRect(Memo).Bottom div Metric.tmHeight);
end;
[TMemo Component] 원하는 라인만큼 스크롤하기
현재상태에서 원하는 x, y만큼 스크롤한다.
DoScroll(Memo1, 10, 10);
procedure DoScroll(Memo : TMemo; x : integer; y : integer);
begin
Memo.Perform(EM_LINESCROLL, x, y);
end;
[TRichEdit Component] 블록설정부분 폰트 변경하기
리치에디트컴포넌트는 메모컴포넌트와는 달리 설정부분만 폰트를 변경한다던가, 정렬상태를 바꾸는게 가능하다.
procedure TForm1.FontBtnClick(Sender : TObject);
begin
if RichEdit1.SelLength > 0 then
begin
FontDialog1.Font.Assign(RichEdit1.DefAttributes);
if FontDialog1.Execute then
RichEdit1.SelAttributes.Assign(FontDialog1.Font);
end
else
ShowMessage('No Text Selected');
end;
[TRichEdit Component] 블록설정부분 속성 변경하기
아래의 소스는 굵게(Bold) 속성을 지정한다.
이탤릭(fsItalic), 밑줄(fsUnderLine) 등의 속성도 마찬가지로 바꿀 수 있다.
procedure TForm1.BoldBtn(Sender : TObject);
begin
if BoldBtn.Down then
RichEdit1.SelAttributes.Style := RichEdit1.SelAttributes.Style + [fsBold]
else
RichEdit1.SelAttributes.Style := RichEdit1.SelAttributes.Style - [fsBold];
end;
[TRichEdit Component] 블록설정부분 복사, 삭제, 잘라우기, 붙이기 설정방법
interface부의 uses절에 Clipbrd를 추가한다.
procedure TForm1.CopyBtnClick(Sender : TObject);
begin
RichEdit1.CopyToClipboard; {복사}
RichEdit1.CutToClipboard; {잘라두기}
RichEdit1.ClearSelection; {지우기 - 클립보드에 저장되지 않는다}
if Clipboard.HasFormat(CF_TEXT) then begin
PasteBtn.Enabled := True; {복사가 되었으면 붙이기 버튼을 활성화}
end;
end;
procedure TForm1.PasteBtnClick(Sender : TObject);
begin
RichEdit1.PasteFromClipboard;
end;
[TRichEdit Component] Insert 키 상태 알아내기
이 소스는 RichEdit 컴포넌트에서만 사용할 수 있다.(메모컴포넌트는 삽입, 수정의 개념이 없음)
procedure TForm1.RichEdit1Key(Sender: TObject; var Key: Word; Shift: TShiftState);
var
ret : integer;
begin
ret := GetKeyState(45);
if ret=1 then
Label1.Caption := 'Overwrite'
else
Label1.Caption := 'Insert';
end;
[Find Dialog Component] 리치에디트에서 문자열찾기
먼저 폼에 Memo, FindDialog컴포넌트를 배치합니다. 델파이 도움말에서 참조했습니다.
procedure TForm1.FindBtnClick(Sender : TObject);
begin
FindDialog1.Execute;
{ or ReplaceDialog1.Execute;}
end;
procedure TForm1.FindDialog1Find(Sender: TObject);
var
SelPos: Integer;
begin
with TFindDialog(Sender) do
begin
{ Perform a global case-sensitive search for FindText in Memo1 }
SelPos := Pos(FindText, Memo1.Lines.Text);
if SelPos > 0 then
begin
Memo1.SelStart := SelPos - 1;
Memo1.SelLength := Length(FindText);
end
else MessageDlg(Concat('Could not find "', FindText, '" in Memo1.'),
mtError,[mbOk], 0);
end;
end;
procedure TForm1.ReplaceDialog1Replace(Sender: TObject);
var
SelPos: Integer;
begin
with TReplaceDialog(Sender) do
begin
{ Perform a global case-sensitive search for FindText in Memo1 }
SelPos := Pos(FindText, Memo1.Lines.Text);
if SelPos > 0 then
begin
Memo1.SelStart := SelPos - 1;
Memo1.SelLength := Length(FindText);
{ Replace selected text with ReplaceText }
Memo1.SelText := ReplaceText;
end
else MessageDlg(Concat('Could not find "', FindText, '" in Memo1.'),
mtError,[mbOk], 0);
end;
end;
Windows API 함수인 SetSysModalWindow를 사용하면 가능합니다.
다음은 System Modal 창을 보여주는 간단한 예제입니다.
procedure TMainForm1.Create(Application) do
begin
SetSysModalWindow(Handle);
end;
다음과 같이 선언합니다.
implementation
{$R C:\Delphi\MyDir\MyRes.Res} <- .RES 화일이 있는 경로명과 파일명
위와 같이 선언한 후에 사용시에는 다음과 같이 Windows API함수를 이용합니다.
Image1.Picture.Bitmap.Handle := LoadBitmap(HInstance, 'BITMAP1');
Windows API 함수인 GetVersion 을 쓰시면 가능합니다.
다음은 버튼을 누르면 윈도우의 버전을 보여줍니다.
procedure TForm1.Button1Click(Sender: TObject);
Var
x :longint;
y,z :integer;
begin
x := GetVersion;
y := integer(x and $ff);
z := integer((x shr 8) and $ff);
Edit1.Text := IntToStr(y);
Edit2.Text := IntToStr(z);
end;
Window API함수인 ShowCursor 에서 값을 False로 줍니다.
<정의된 message handler에 다른 작업을 추가하려면>
예를 들어 CM_DIALOGKEY message가 발생되었을 때 원하는 작업을 추가하려고한다면 public section에 다음과 같이 선언합니다.
Procedure CMDialogKey(var Message: TCMDialogKey);message CM_DIALOGKEY;
procedure이름을 message 이름에서 _(밑줄) 표시를 뺍니다. procedure의 정의는 다음과 같습니다.
Procedure TForm1.CMDialogKey(var Message: TCMDialogKey);
begin
if CharCode = VK_TAB then begin
{Process the Alt+Tab key here}
result := 1;
exit;
end;
inherited;
end;
result를 1로 setting하면 더 이상 실행시키지 않고 중단시키겠다는 뜻이고, inherited문은 parent handler로 제어를 보냄을 의미합니다. 모든 작업을 일일이 처리하고자 하지 않으면 inherited문을 사용하십시오.
<Run-Time시에 DLL을 Load하고 Free 시키는 방법>
Windows API 함수인 LoadLibrary를 쓰면 Load가 가능합니다. 또한 FreeLibrary를 쓰면 메모리에서 제거할 수 있습니다.
<비정상적으로 종료된 DLL 프로그램을 강제적으로 unload 하는 방법>
Windows API 함수인 GetModuleHandle은 DLL의 handle을 돌려주므로ModuleHandle이 0을 리턴할 때 까지 freelibrary를 call한다. 만약에 DLL이 다른 DLL을 Load 했다면 child DLL을 먼저 free시킨다.
<DLL의 data segment를 fixed에서 movable로 바꾸는 방법>
DLL 외부에서 GlobalPageUnlock(DSEG)를 부르면 됩니다. 이 함수는DLL 소스에서 Pointer등을 이용하지 않는다면 정상적으로 실행될 것입니다.
SetWindowPos나 MoveWindow를 이용하여 좌표값을 음수로 주면 됩니다.
Windows API 함수인 WinExec 를 사용하면 됩니다. 다음은 간단한 예제 코드입니다.
WinExec('프로그램명', SW_SHOW);
<Title Bar가 없는 Form을 움직이게 하려면>
폼위에서 마우스 커서가 움직이면, 윈도우는 폼에 WM_NCHitTest 메시지를보냅니다. 이 때 폼은 마우스가 폼의 어느 위치에 있는지를 메시지로 주게 됩니다. 마우스의 버튼을 누르는 것과 같은 event가 발생하면 윈도우는 이 정보를 써서 특정행동을 수행하게 되는 것입니다.
다음은 WM_NCHitTest 메시지가 특정한 값을 주는 예제 코드입니다.
procedure TNoCapForm.WMNCHitTest(var Msg: TMessage);
begin
if GetAsyncKeyState(VK_LBUTTON) < 0 then
Msg.Result := HTCAPTION
else
Msg.Result := HTCLIENT;
end;
<Resource를 동적으로 load/free 하는 방법>
Windows가 제공하는 LoadResource(), FreeResource() API 함수를사용합니다.
<System 또는 User resource, memory 상태를 구하는 방법>
Windows API를 이용하면 됩니다. GetFreeSystemResource 함수를 참고하시면 됩니다.
다음은 버튼을 누르면 시스템 자원을 보여주는 간단한 코드입니다.
procedure TForm1.Button1Click(Sender: TObject);
begin
Label1.Caption := IntToStr(GetFreeSystemResources(GFSR_SYSTEMRESOURCES));
Label2.Caption := IntToStr(GetFreeSystemResources(GFSR_USERRESOURCES));
Label3.Caption := Formatfloat('#,##0', (GetFreeSpace(0) div 1000));
end;
<Visual Basic의 DoEvent와 같은 기능을 사용하려면>
다음과 같이 함수를 만드실 수 있습니다.
function DoEvents: Boolean;
var msg: TMsg;
begin
while PeekMessage(msg, 0, 0, 0, PM_REMOVE) do
begin
if msg.message = WM_QUIT then
begin
PostQuitMessage(msg.wParam);
DoEvents := true;
exit;
end
else
begin
TranslateMessage(msg);
DispatchMessage(msg);
end;
end;
DoEvents := false;
end;
WinExec 함수는 핸들을 돌려주므로, 이것을 이용합니다.
procedure SomeProc;
var
ProgramHandle : THandle;
begin
ProgramHandle := WinExec('C:\Program.exe', SW_SHOWNORMAL);
{프로그램이 종료될 때까지 반복}
while GetModuleusage(ProgramHandle) <> 0 do application.processmessages;
end;
<프로그램 실행중에 잠시 멈추고 다른 프로세스를 실행시키려면>
다음과 같은 코드를 작성하실 수 있습니다.
procedure TForm1.Delay(msecs:integer);
var
FirstTickCount:longint;
begin
FirstTickCount:=GetTickCount;
repeat
{실행을 잠시 중지하고 다른 프로세스를 실행합니다.}
Application.ProcessMessages;
until ((GetTickCount-FirstTickCount) >= Longint(msecs));
end;
참고로 Application.ProcessMessage 는 메시지 큐에 쌓여있는 메시지중 하나를처리하고 메시지가 큐에 없으면 false를 리턴합 니다.
control object의 pointer를 알고 있다면 PointerToMyControl^.HWindow가 바로 window handle입니다.
만약, control의 handle을 알고 있다면 GetDlgCtrlID() API 함수는 ID를 돌려줍니다.
ControlID := GetDlgCtrlID(ControlHandle);
만약 contorl의 pointer를 모르고 ID만 알고 있다면, GetDlgItem() API 함수는handle을 돌려줍니다.
ControlHandle := GetDlgItem(DialogHandle, ControlID);
다음의 함수는 Application이라는 개체의 ExeName 속성으로부터 디렉토리 경로를 추출해 냅니다.
function GetExePath : String;
var
LastBackSlashPos, Index : Integer;
begin
Result := Application.ExeName;
for Index := 1 to length(Result) do
if Result[Index] = '\' then LastBackSlashPos := Index;
{'\' 기호가 붙지 않도록 하려면 LastBackSlashPos 에서 1을 빼야합니다. }
Result[0] := chr(LastBackSlashPos - 1);
end;
MKDIR procedure를 이용하면 됩니다.
MkDir('C:\Delphi\MyDir');
<MediaPlayer를 이용하지 않고 sound를 발생할 수 있는 방법>
mmSystem에 있는 SndPlaySound Function을 이용하면 됩니다.
SndPlaySound('C:\Windows\Ding.WAV', snd_Async);
다음 Windows 메시지를 처리하는 procedure를 참고하십시오.
procedure YieldToOthers ;
var MSG : TMSG ;
begin
while PeekMessage(MSG, 0,0,0,PM_REMOVE) do begin
if Msg.Message = WM_QUIT then exit ;
TranslateMessage(Msg) ;
DispatchMessage(Msg) ;
end ;
end ;
<Windows의 Main Message Procedure를 만드는 방법>
다음 예제 procedure를 참고하십시오.
procedure TForm1.ClientWndProc(VAR Message: TMessage);
begin
with Message do
case Msg of
WM_MOUSEMOVE : Memo1.Lines.Add('Mouse Move') ;
WM_LBUTTONDOWN : Memo1.Lines.Add('LeftButton Down') ;
else
Result := CallWindowProc(FPrevClientProc, Handle, Msg, wParam, lParam);
end;
end;
<다른 Application의 메뉴 기능을 실행하도록 하려면>
다음 예제 procedure를 참고하십시오.
CurrWnd := GetWindow(application.handle, gw_hwndfirst);
length := GetWindowText(Currwnd, tmpstr, 255);
if length > 0 then
begin
if (pos('훈민정음', strpas(tmpstr)) > 0) and (strpas(pAttach^.filepath.tmpstr)<> nil) then
CurrWnd := 0;
end;
tmpname := ExtractFilename(strpas(pAttach^.filepath));
While CurrWnd <> 0 do
begin
length := GetWindowText(Currwnd, tmpstr, 255);
if (length > 0) and (pos('훈민정음', strpas(tmpstr) > 0) and (pos(tmpname,StrPas(tmpstr)) > 0) then
break;
CurrWnd := GetWindow(CurrWnd, GW_HWNDNEXT);
Application.ProcessMessages;
end;
Handle := CurrWnd;
if Handle <> 0 then
begin
SendMessage(Handle, WM_COMMAND, 4005, 0);
SendMessage(Handle, WM_SYSCOMMAND, SC_CLOSE, 0);
end;
다음과 같이 WM_SYSCOMMAND 메시지를 처리하면 됩니다.
type
TForm1 = class(TForm)
public :
procedure WMSysCommand(var Msg: TWMSysCommand); message WM_SYSCOMMAND;
end;
procedure TForm1.WMSysCommand(var Msg:TWMSysCommand) ;
begin
{최소화/최대화 버튼을 누를때 아무 작용을 하지 않게 합니다}
if (Msg.CmdType = SC_MINIMIZE) or (Msg.CmdType = SC_MAXIMIZE) then
Msg.CmdType := SC_RESTORE;
DefaultHandler(Msg);
end;
<DPR 화일의 Application.Run이 실행되기 전에 Windows 메시지를 가로채는방법>
다음과 같이 새로운 Windows Message procedure를 정의하고 그것을Main Windows procedure로 설정합니다. 다음 예제 procedure를 참고하십시오.
program Project1;
uses
Forms, messages, wintypes, winprocs,
Unit1 in 'UNIT1.PAS';
{$R *.RES}
var
OldWndProc: TFarProc;
function NewWndProc(hWndAppl: HWnd; Msg, wParam: Word; lParam: Longint):Longint; export;
begin
result := 0; { Default WndProc return value }
{message 처리 루틴이 들어갈 곳}
result := CallWindowProc(OldWndProc, hWndAppl, Msg, wParam, lParam);
end;
begin
Application.CreateForm(TForm1, Form1);
OldWndProc := TFarProc(GetWindowLong(Application.Handle, GWL_WNDPROC));
SetWindowLong(Application.Handle, GWL_WNDPROC, longint(@NewWndProc));
Application.Run;
end.
ToolHelp unit에 정의되어 있는 함수들을 이용하면 됩니다. 다음은 TaskFirst, TaskNext 등을 이용한 예제입니다.
function isTaskInstance(HInst : Longint) : Boolean;
var CurrentTask : TTaskEntry;
Success : boolean;
begin
Result := false;
Yield;
CurrentTask.dwSize := SizeOf(CurrentTask);
Success := TaskFirst(@CurrentTask);
while Success do begin
if CurrentTask.HInst = HInst then begin
Result := true;
exit;
end;
Success := TaskNext(@CurrentTask);
end;
end;
'Programming > Delphi' 카테고리의 다른 글
Thread 정리 2 (0) | 2010.06.30 |
---|---|
Thread 정리 (0) | 2010.06.30 |
[팁] 쓸만한 함수 (0) | 2010.06.30 |
이미지 포맷 확인하기 (0) | 2010.06.30 |
enum 타입 값을 String 값으로 얻어오기 (0) | 2010.06.30 |