Form Style - fsStayOnTop 효과

 SetWindowPos(Handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE or SWP_NOSIZE)

<-> SetWindowPos(Handle, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE or SWP_NOSIZE);

 

출처 :  http://www.delmadang.com/community/bbs_view.asp?bbsNo=17&bbsCat=41&indx=405581&keyword1=fsStayOnTop&keyword2=

이 글은 스프링노트에서 작성되었습니다.

 폼 소스 부분은 생략하고 처리부분만 기술한다.

  • Form Style : fsStayOnTop
  • 해당 폼을 TObject 형태로 구현 함수로 넘긴다
    (경우에 따라서 TForm으로 넘기던지 상속클래스 만들어서 넘기던지...그건 알아서...단, 구현부분 파라메터 타입과 구현부분도 거기에 맞추어서 ^^)

 

 

 구현 부분

  1. procedure ShowSaveDialogBox(Sender : TObject = nil)
  2. var
  3. saveDlg : TSaveDialog;
  4. SenderFormStyle : TFormStyle;
  5. isSenderFormStyleChange : Boolean;
  6. begin
  7. isSenderFormStyleChange := False;

    if (Sender <> nil) and Assigned(Sender) and (Sender is TForm) then

    saveDlg := TSaveDialog.Create(TForm(Sender))

    else

    saveDlg := TSaveDialog.Create(nil);

  8. saveDlg.Title := '파일 저장';
  9. saveDlg.Filter := 'TEXT 파일|*.txt';
  10. saveDlg.DefaultExt := 'txt';
  11. saveDlg.Options := saveDlg.Options + [ofOverwritePrompt];
  12. saveDlg.FileName := 'ExportText' + '.xls';
  13. if (Sender <> nil) and Assigned(Sender) and (Sender is TForm) and (TForm(Sender).FormStyle = fsStayOnTop) then
  14. begin
  15. //BEGIN 1안. 폼을 아래로 위치 시킨다(사라지는 효과 나타남)
  16. TForm(Sender).SendToBack;
  17. isSenderFormStyleChange = True;
  18. //END 1안.
  19. //BEGIN 2안. 폼을 일반 폼으로 변경함(화면이 심하게 깜빡거리는 단점)
    SenderFormStyle := TForm(Sender).FormStyle;
  20. isSenderFormStyleChange := True;
  21. TForm(Sender).FormStyle := fsNormal;
  22. Application.ProcessMessages; //(생략가능 혹시나 해서.....^^;;)
  23. //END 2안.
  24.  end;
  25. if saveDlg.Execute then
  26. begin
  27.  {처리 코드}
  28. end;
  29. if isSenderFormStyleChange = True then

    begin

  30. //1안.
  31. TForm(Sender).BringToFront;
  32. //2안.
  33. TForm(Sender).FormStyle := SenderFormStyle;
  34. Application.ProcessMessages; //(생략가능 혹시나 해서.....^^;;)
  35. end;
  36. end;

 

출처 : 자작(userpark)

이 글은 스프링노트에서 작성되었습니다.

 Showmessage 박스 Owner가 Application으로 되어져 있는 현상 때문에 Form이 StayOnTop일 경우 아래에 숨어버리는 현상 발생

해결 방법은 아래 소스.... Screen.ActiveForm을 이용한 방법

 

  1. TForm1 = class(TForm)
  2. {...생략...}
  3. procedure OnScreenActiveFormChange(Sender: TObject);
  4. private
  5. {...생략...}
  6. protected
  7. {...생략...}
  8. public
  9. {...생략...}
  10. end;
  11. procedure TForm1.FormCreate(Sender: TObject);
    begin
  12. Screen.OnActiveControlChange := OnScreenActiveFormChange;
  13. end;
  14. procedure TfrmUbBase_S.OnScreenActiveFormChange(Sender: TObject);
  15. begin
  16. if Assigned(Screen.ActiveForm) and ( (UpperCase(Screen.ActiveForm.ClassName) = UpperCase('TMessageForm')) ) then
  17. begin
  18. SetWindowPos(Screen.ActiveForm.Handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE or SWP_NOSIZE);
  19. end;
  20. end;

 

출처 : 델마당 for Modify By Userpark

이 글은 스프링노트에서 작성되었습니다.

 Showmessage 박스 Owner가 Application으로 되어져 있는 현상 때문에 Form이 StayOnTop일 경우 아래에 숨어버리는 현상 발생

해결 방법은 아래 소스.... Screen.ActiveForm을 이용한 방법

 

  1. TForm1 = class(TForm)
  2. {...생략...}
  3. procedure OnScreenActiveFormChange(Sender: TObject);
  4. private
  5. {...생략...}
  6. protected
  7. {...생략...}
  8. public
  9. {...생략...}
  10. end;
  11. procedure TForm1.FormCreate(Sender: TObject);
    begin
  12. Screen.OnActiveControlChange := OnScreenActiveFormChange;
  13. end;
  14. procedure TfrmUbBase_S.OnScreenActiveFormChange(Sender: TObject);
  15. begin
  16. if Assigned(Screen.ActiveForm) and ( (UpperCase(Screen.ActiveForm.ClassName) = UpperCase('TMessageForm')) ) then
  17. begin
  18. SetWindowPos(Screen.ActiveForm.Handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE or SWP_NOSIZE);
  19. end;
  20. end;

 

출처 : 델마당 for Modify By Userpark

이 글은 스프링노트에서 작성되었습니다.

다음은 동적(Static) DLL로 구현 되어져 있다.

  • 정적(Static) DLL 이란? 본래의 DLL이라기 보다는 코드의 큰 함수들을 따로 모듈별로 분리 했다가 실행 시 함께 처리한다.
  • 동적(Dynamic) DLL(런타임 로딩) 이란 ? DLL은 GetProcAddress라는 API를 사용하여 필요에 따라 첨가하고 필요에 따라 해제시킬 수 있다.

DLL 소스 및 정적 DLL 호출 방법은 다음 글을 참고 하기 바란다.

2010/04/27 - [Language/Delphi] - [Delphi] DLL 호출 규칙(Calling Convention) 테스트용 DLL 및 Source

다음 소스는 Delphi 2010에서 제작 되었으나 기본 사용법은 동일하다.


  1: unit UB_Main_DynDLL;
  2: 
  3: interface
  4: 
  5: uses
  6:   Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  7:   Dialogs, StdCtrls;
  8: 
  9: type
 10:   TfrmUBMainDynDLL = class(TForm)
 11:     btnPascal: TButton;
 12:     edtPascal: TEdit;
 13:     btnCdecl: TButton;
 14:     edtCdecl: TEdit;
 15:     btnStdcall: TButton;
 16:     edtStdcall: TEdit;
 17:     procedure btnPascalClick(Sender: TObject);
 18:     procedure btnCdeclClick(Sender: TObject);
 19:     procedure btnStdcallClick(Sender: TObject);
 20:   private
 21:     { Private declarations }
 22:   public
 23:     { Public declarations }
 24:   end;
 25: 
 26: var
 27:   frmUBMainDynDLL: TfrmUBMainDynDLL;
 28: 
 29: implementation
 30: 
 31: const
 32:   ImportDLLFile = 'UPCallTypeDLLTest.dll';
 33:   Msg = '안녕! 세계 (Hellow World!)';   // Hellow World! 국산화 버전 ㅎㅎ
 34: 
 35: var
 36:   DLLCallTypePascal : function (AStr : string)  : PChar;  pascal;
 37:   DLLCallTypeCdecl  : function (AStr : string)  : PChar;  cdecl;
 38:   DLLCallTypeStdcall: function (AStr : string)  : PChar;  stdcall;
 39: 
 40: {$R *.dfm}
 41: 
 42: procedure TfrmUBMainDynDLL.btnCdeclClick(Sender: TObject);
 43: var
 44:   H : HINST;
 45:   S : PChar;
 46: begin
 47:   H := LoadLibrary(PChar(ImportDLLFile));
 48:   if H <= 0 then
 49:   begin
 50:     ShowMessage('로딩 에러 : ' + IntToStr(GetLastError));
 51:   end else begin
 52:     try
 53:       @DLLCallTypeCdecl := GetProcAddress(H, Pchar('DLLCallTypeCdecl'));
 54:       S := DLLCallTypeCdecl(Msg);
 55:       if H <> 0 then
 56:         edtCdecl.Text := S
 57:       else
 58:         edtCdecl.Text := 'ERROR!!';
 59:     finally
 60:       FreeLibrary(H);
 61:     end;
 62:   end;
 63: end;
 64: 
 65: procedure TfrmUBMainDynDLL.btnPascalClick(Sender: TObject);
 66: var
 67:   H : HINST;
 68:   S : PChar;
 69: begin
 70:   H := LoadLibrary(PChar(ImportDLLFile));
 71:   if H <= 0 then
 72:   begin
 73:     ShowMessage('로딩 에러 : ' + IntToStr(GetLastError));
 74:   end else begin
 75:     try
 76:       @DLLCallTypePascal := GetProcAddress(H, Pchar('DLLCallTypePascal'));
 77:       S := DLLCallTypePascal(Msg);
 78:       if H <> 0 then
 79:         edtPascal.Text := S
 80:       else
 81:         edtPascal.Text := 'ERROR!!';
 82:     finally
 83:       FreeLibrary(H);
 84:     end;
 85:   end;
 86: end;
 87: 
 88: procedure TfrmUBMainDynDLL.btnStdcallClick(Sender: TObject);
 89: var
 90:   H : HINST;
 91:   S : PChar;
 92: begin
 93:   H := LoadLibrary(PChar(ImportDLLFile));
 94:   if H <= 0 then
 95:   begin
 96:     ShowMessage('로딩 에러 : ' + IntToStr(GetLastError));
 97:   end else begin
 98:     try
 99:       @DLLCallTypeStdcall := GetProcAddress(H, Pchar('DLLCallTypeStdcall'));
100:       S := DLLCallTypeStdcall(Msg);
101:       if H <> 0 then
102:         edtStdcall.Text := S
103:       else
104:         edtStdcall.Text := 'ERROR!!';
105:     finally
106:       FreeLibrary(H);
107:     end;
108:   end;
109: end;
110: 
111: end.
112: 





출처 : 자작(http://userpark.net)

DLL호출 규칙에 대하여 먼저 언급하고자 한다.

Delphi는 다른 랭귀지에서 사용된 함수들을 쉽게 호출 할 수 있도록 여러 가지 호출 규칙을 가진다.

아래와 같이 5가지 방법이 있다.

  1. Register(__fastcall) : 레지스터에 등록하여 호출하는 방식
  2. stdcall(__stdcall) : 가장 일반적으로 활용하는 방식으로 윈도우 표준
  3. cdecl(__cdecl) : 가변인자가 있는 경우
  4. pascal(__pascal) : Delphi 최적화 코드를 생성하고자 할 때 스택으로 인자를 저장하는 방식보다는 레지스터를 경유하여 속도 향상
  5. safecall : OLE 방식에서 이용

참고 : http://www.delmadang.com/community/bbs_view.asp?bbsNo=3&bbsCat=42&indx=195902&keyword1=dll&keyword2=호출규칙

※pascal 경우 속도 향상이 된다고 책에는 나와있으나 실제 테스트는 하지 않음.

본 글에서는 stdcall,cdecl,pascal 3가지에 대해서만 샘플을 제공하여 드리겠습니다.

아래 소스를 콜타입들을 바꿔가면서 DLL과 App에서 서로 테스트 해보기시기 바랍니다.

그런데 이상하게도 테스트 하면서 stdcall과 pascal은 서로 상호 호환이 완벽하게 이루어졌습니다. 이 해당 소스만이 그런건지 정확히는 현재 알 수 없습니다.

지금까지 저는 DLL을 안 쓰다가 이번에 새로운 일이 생겼는데 DLL을 호출해서 사용해야 할 일이 생겨서 이것 저것 테스트 하다가 이런 문서도 만들게 되었습니다.

(기존 Delphi만 이용시에는 dcu파일로 배포등을 하여 DLL의 필요성을 알지 못했습니다. ^^;;)

정확한 개념이 잡힌 소스인지… 저도 장담을 못하지만 여러가지로 도움이 되었으면 좋겠습니다.

또한 DLL 생성 및 Delphi 기초에 대하여서는 기타 유용한 사이트 및 책을 이용하시기 바랍니다.


아래 방법으로 공부하시기 바랍니다.(저도 이걸로 공부 중)

  1. UPCallTypeDLLTest.dll 을 만든다
  2. UPCallTypeDLLTestApp.exe에서 상기 DLL을 호출한다.
  3. DLL과 APP를 서로 콜방식을 변경하여 가면서 오류 사항 및 반영내용을 스스로 공부한다.

아래 소스는 Delphi 2010으로 만들었습니다.(Delphi 7로 하려다가 그냥~)


Import 해 올 DLL 파일을 반드시 아래 경로에 존재 하여야 한다.
  • [%SystemRoot%] (Windows 디렉토리)
  • [%SystemRoot%]\system32\ 경로 (Microsoft Windows XP 일 경우)
  • 실행파일(현재 작업) 디렉토리에 같이 위치
  • 환경변수 PATH 상의 경로(비추천)

  • UPCallTypeDLLTest.dll
  1: library UPCallTypeDLLTest;
  2: 
  3: uses
  4:   SysUtils,
  5:   Classes,
  6:   Dialogs;
  7: 
  8: {$R *.res}
  9: 
 10: function DLLCallTypePascal(AStr : string) : PChar; pascal;
 11: var
 12:   S : string;
 13: begin
 14:   S := AStr;
 15:   S := 'DLL 함수 테스트 : ' + S + ' - pascal';
 16:   ShowMessage(S);
 17:   Result := PChar(S);
 18: end;
 19: 
 20: function DLLCallTypeCdecl(AStr : string) : PChar; cdecl;
 21: var
 22:   S : string;
 23: begin
 24:   S := AStr;
 25:   S := 'DLL 함수 테스트 : ' + S + ' - cdecl';
 26:   ShowMessage(S);
 27:   Result := PChar(S);
 28: end;
 29: 
 30: function DLLCallTypeStdcall(AStr : string) : PChar; stdcall;
 31: var
 32:   S : string;
 33: begin
 34:   S := AStr;
 35:   S := 'DLL 함수 테스트 : ' + S + ' - stdcall';
 36:   ShowMessage(S);
 37:   Result := PChar(S);
 38: end;
 39: 
 40: exports
 41:   DLLCallTypePascal
 42:   ,DLLCallTypeCdecl
 43:   ,DLLCallTypeStdcall
 44:   ;
 45: 
 46: begin
 47: end.

다음은 정적(Static) DLL로 구현 되어져 있다.

  • 정적(Static) DLL 이란? 본래의 DLL이라기 보다는 코드의 큰 함수들을 따로 모듈별로 분리 했다가 실행 시 함께 처리한다.
  • 동적(Dynamic) DLL(런타임 로딩) 이란 ? DLL은 GetProcAddress라는 API를 사용하여 필요에 따라 첨가하고 필요에 따라 해제시킬 수 있다.
  • UPCallTypeDLLTestApp.exe
      - UB_Main.pas
  1: unit UB_Main;
  2: 
  3: interface
  4: 
  5: uses
  6:   Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  7:   Dialogs, StdCtrls;
  8: 
  9: type
 10:   TfrmUBMain = class(TForm)
 11:     btnPascal: TButton;
 12:     edtPascal: TEdit;
 13:     btnCdecl: TButton;
 14:     edtCdecl: TEdit;
 15:     btnStdcall: TButton;
 16:     edtStdcall: TEdit;
 17:     procedure btnPascalClick(Sender: TObject);
 18:     procedure btnCdeclClick(Sender: TObject);
 19:     procedure btnStdcallClick(Sender: TObject);
 20:   private
 21:     { Private declarations }
 22:   public
 23:     { Public declarations }
 24:   end;
 25: 
 26: var
 27:   frmUBMain: TfrmUBMain;
 28: 
 29: const
 30:   ImportDLLFile = 'UPCallTypeDLLTest.dll';
 31:   Msg = '안녕! 세계 (Hellow World!)';   // Hellow World! 국산화 버전 ㅎㅎ
 32: 
 33: function DLLCallTypePascal(AStr : string)   : PChar;  pascal;   external ImportDLLFile;
 34: function DLLCallTypeCdecl(AStr : string)    : PChar;  cdecl;    external ImportDLLFile;
 35: function DLLCallTypeStdcall(AStr : string)  : PChar;  stdcall;  external ImportDLLFile;
 36: function DLLCallTypeStdcallNickName(AStr : string)  : PChar;  stdcall;  external ImportDLLFile name 'DLLCallTypeStdcall';
 37: 
 38: implementation
 39: 
 40: {$R *.dfm}
 41: 
 42: procedure TfrmUBMain.btnCdeclClick(Sender: TObject);
 43: var
 44:   S : PChar;
 45: begin
 46:   S := DLLCallTypeCdecl(Msg);
 47:   edtCdecl.Text := S;
 48: end;
 49: 
 50: procedure TfrmUBMain.btnPascalClick(Sender: TObject);
 51: var
 52:   S : PChar;
 53: begin
 54:   S := DLLCallTypePascal(Msg);
 55:   edtPascal.Text := S;
 56: end;
 57: 
 58: procedure TfrmUBMain.btnStdcallClick(Sender: TObject);
 59: var
 60:   S : PChar;
 61: begin
 62:   S := DLLCallTypeStdcall(Msg);
 63:   edtStdcall.Text := S;
 64: end;
 65: 
 66: end.

 출처 : 자작(http://userpark.net)


PS) 본 소스를 바탕으로 .NET C#과 Visual Basic에서 호출하여 사용하는 방법을 추후 올리겠습니다.

      (대부분 C++에서 DLL을 만드는데 전 C++이 약한 관계로 ^^;;)

UPCallTypeDLLTestForDelphi2010.7z

UPCallTypeDLLTestAppForDelphi2010.7z


UPCallTypeDLLTestGroupForDelphi2010(All).7z


Tistory 태그: ,,,

Since I need to export MapInfo vector TAB files to ESRI SHP within an MapX application, I have developed a Delphi function doing so with Universal Translator from MapInfo Pro.
I am not aware of any copyrights from MapInfo Corp and Safe.com. It would be nice if MapX was distributed with the IMUT.exe from Universal Translator of MapInfo Pro.
If you copy UE directory from MI Pro the following function will do the job.
{ ============================================================================ }
function Tab2Shp(srcfile, destfile : String) : Boolean; 
  //Convert a source MapInfo tab file to a destination ESRI shape file with external Universal Translator macro 
var
  str : String; //String holder
  pathIMUT : String; //Path to external FME application
  pathSrc : String; //PAth to Source file (MapInfo TAB vector files)
  pathDest : String; //Path to destination files (ESRI SHP vector files)
  tabnam : String; //Source table name
  tmpdat : string; //Temp dat file for IMUT
  sParam : string; //Parametre to INUT.EXE
  FileStream : TFileStream; //Used to write hggtemp2.dat
  StringList : TStringList;
begin
  Result := False;
  //Step 1: Gernerate FME script - Run command line:
  pathIMUT := ExtractFilePath(Application.ExeName)+'UT\';
  pathSrc := ExtractFilePath(srcfile);
  pathSrc := Copy(pathSrc,1,Length(pathSrc)-1) + '/'; //Change trailing \ to /
  pathSrc := AnsiQuotedStr(pathSrc,#34); //Add Quoates and trailing space
  tmpdat := AnsiQuotedStr('hggtemp1.dat',#34);
  pathDest := ExtractFilePath(destfile);
  tabnam := Copy(ExtractFileName(srcfile),1,Length(ExtractFileName(srcfile))-4); //Get MapInfo Tabelname
  sParam := 'CFGenerate MAPINFO SHAPE ' + pathSrc + ' ' + tmpdat + ' LOG_STANDARDOUT YES +ID ' + tabnam;
  //Batch = IMUT.EXE CFGenerate MAPINFO SHAPE "C:\HGG\Code\UT\MIdir/" "hggtemp1.dat" LOG_STANDARDOUT YES +ID "komg2002"
  ShellExecute(Application.Handle,'OPEN',PChar(pathIMUT+'IMUT.EXE'),PChar(sParam),PChar(pathIMUT),SW_HIDE);
  //Step 2: Create control file - Named hggtemp2.dat
  StringList := TStringList.Create;
  StringList.Add('MACRO _EXTENSION TAB');
  StringList.Add('MACRO _BASENAME ' + tabnam);
  StringList.Add('MACRO _FULLBASENAME ' + tabnam);
  StringList.Add('MACRO SourceDataset ' + pathSrc);
  pathDest := Copy(pathDest,1,Length(pathDest)-1); // Remove trailing slash
  StringList.Add('MACRO DestDataset ' + pathDest);
  StringList.Add('INCLUDE hggtemp1.dat'); //Add double quoates
  tabnam := AnsiQuotedStr(tabnam,#34); //Get MapInfo Tabelname
  StringList.Add('MAPINFO_IDs ' + tabnam);
  StringList.Add('MAPINFO_IN_IDs ' + tabnam);
  StringList.SaveToFile(pathIMUT+'hggtemp2.dat');
  StringList.Free;
  //Step 3: Final executation - Command line: imut.exe hggtemp2.dat
  sParam := 'hggtemp2.dat';
  ShellExecute(Application.Handle,'OPEN',PChar(pathIMUT+'IMUT.EXE'),PChar(sParam),PChar(pathIMUT),SW_HIDE);
  Result := True;
end;

Get Delphi 6 source and sample application from

http://www.lanstorp.com/Files/Tab2Shp.zip

 

출처 : http://community.mapinfo.com/forums/thread.jspa?threadID=3457

 

+ Recent posts