Programming/Delphi

[팁] 쓸만한 함수 2

통통만두 2010. 6. 30. 15:27
반응형

[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;

 

<System Modal 폼을 만들려면>

Windows API 함수인 SetSysModalWindow를 사용하면 가능합니다.

다음은 System Modal 창을 보여주는 간단한 예제입니다.

procedure TMainForm1.Create(Application) do
begin
   SetSysModalWindow(Handle);
end;

 

<.RES 화일에서 비트맵을 불러오려면>

다음과 같이 선언합니다.

implementation
{$R C:\Delphi\MyDir\MyRes.Res} <- .RES 화일이 있는 경로명과 파일명

위와 같이 선언한 후에 사용시에는 다음과 같이 Windows API함수를 이용합니다.

Image1.Picture.Bitmap.Handle := LoadBitmap(HInstance, 'BITMAP1');

 

<Win95 와 W3.X 를 구별하는 법>

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등을 이용하지 않는다면 정상적으로 실행될 것입니다.

 

<최소화되어 있는 Icon을 안보이게 하는 방법>

SetWindowPos나 MoveWindow를 이용하여 좌표값을 음수로 주면 됩니다.

 

<외부의 Exe 화일 호출하는 방법>

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의 handle이나 ID를 얻는 방법>

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;

 

<Directory를 만드는 방법>

MKDIR procedure를 이용하면 됩니다.

MkDir('C:\Delphi\MyDir');

 

<MediaPlayer를 이용하지 않고 sound를 발생할 수 있는 방법>

mmSystem에 있는 SndPlaySound Function을 이용하면 됩니다.

SndPlaySound('C:\Windows\Ding.WAV', snd_Async);

 

<Windows의 Message를 처리하는 방법>

다음 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.

 

<Task Handling 방법>

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