삽질하는플머

라자루스의 LCL 폼에 ActiveX 객체 올리기.

Lazarus

간만에 라자루스 관련 포스팅. 

저녁 먹고 라자루스 포럼을 뒤져보다 재미난 주제를 발견. 
http://www.lazarus.freepascal.org/index.php/topic,9311.0.html 

윈도에서 라자루스 LCL폼 위에 ActiveX 컨트롤을 올릴 수 있느냐는 질문. 오~!!
라자루스의 포터블한 특성이 사라지네 어쩌네 이런 저런 갑론을박이 있었지만,
어쨌건 글타래 말미에 ATL.DLL 을 사용한 멋진 해법이 올라와있다. 
빈 LCL폼 위에 TPanel을 올리고 다음과 같이 코딩. 


......

implementation


......

uses
  Windows, ComObj;

type
  PIUnknown=^IUnknown;
  TAtlAxAttachControl = function(Control:IUnknown; hwind:hwnd;ppUnkContainer:PIUnknown): HRESULT; stdcall;

........

constructor TForm1.Create(aOwner: TComponent);
var
  atl: hModule;
  AtlAxAttachControl:TAtlAxAttachControl;
  WebBrower:variant;
begin
  inherited Create(aOwner);
  atl := LoadLibrary('atl.dll');
  AtlAxAttachControl := TAtlAxAttachControl(GetProcAddress(atl, 'AtlAxAttachControl'));

  WebBrower:= CreateOleObject('Shell.Explorer');
  AtlAxAttachControl(WebBrower, Panel1.Handle, nil);
  WebBrower.Navigate('http://oranke.tistory.com');
end;




실행시켜본 결과는 짜잔~~


그 밑에 딸려있는 idl2pas 에 대한 링크도 재미나 보인다. 
http://www.nohl.eu/tech-resources/using-typelibs-with-freepascal/ 

다음에 시간날 때 뒤져봐야지... 


달력 컨트롤

Lazarus/KOL-CE
라자루스를 어디에 쓸까 고민하다가... 음력에 대한 공부도 할 겸 "달 구경" 프로그램을 짬짬이 만들고 있다.
날짜 선택을 위해 달력 컨트롤을 올려놓으려고 했더니... 응? 델파이의 TDateTimePicker에 해당하는 TKOLDateTimePicker 는 있는데 TMonthCalendar에 해당하는 컨트롤이 없다. 허걱~~ fpc의 wince 유니트를 열어보니 DateTimePicker와 MonthCal에 사용되는 ICC_DATE_CLASSES 가 주석으로 막혀있네~ (라자루스 0.9.24 의 LCL 윈CE 인터페이스는 현재 베타버전이다.)

그렇다면 KOL의 TKOLDateTimePicker 는 뭘까 싶어 다시 KOL.pas 를 뒤져보니... 여기에 다시 재정의 되어있었다. 그러나 애석하게도 달력 컨트롤에 대한 코드는 찾아볼 수 없었다.

처음에는 간단히 LCL로 DLL을 만들어 쓰려고 했었는데... 위에서 언급했듯이 아직 윈CE 인터페이스가 베타라 arm-wince 로 달력 컨트롤을 컴파일하면 에러가 발생한다. 뭐 여차저차해서 만들기로 했고, 아직 내공부족으로 KOL 컴포넌트화 할 수는 없었지만 그럭저럭 쓸만하기에 방법을 정리 해 본다.

달력 컨트롤에 관련된 상수들은 evc와 함께 설치한 STANDARDSDK 5.0 에 정의되어 있으며 "C:\Program Files\Windows CE Tools\wce500\STANDARDSDK_500\Include\...\commctrl.h" 에서 찾을 수 있다. 이 파일을 번역하려고 슬쩍 훑어보니 다행히 상수 및 구조체가 윈도 32와 99% 동일하다. 그렇다면?? 델파이의 VCL을 가져와 쓰자.


VCL은 오픈소스가 아니므로 여기에 옮길 수 없다. 델파이 5.0을 기준으로 과정만 소개 해 본다.


1. 먼저 라자루스의 File->NewUnit 를 선택, 새로 만들 달력 컨트롤이 담길 유니트를 만들어 준다. 이름은 적당히.

2. uses 섹션에는 Windows, Messages, KOL, CommCtrl 유니트를 적어넣는다.

3. ...\Delphi5\source\rtl\win\commctrl.pas 파일을 열고 다음 내용들을 복사 해 온다.

3-1. 6371번 줄 (MONTHCAL CONTROL) 부터 6664번 줄 (MonthCal_GetUnicodeFormat) 까지 interface 섹션에 복사 해 넣는다.

3-2. 8508번 줄 (MonthCal_GetCurSel 함수) 부터 8623번 줄 까지 implementation 섹션에 복사 해 넣는다.

3-3. MonthCal_SetUnicodeFormat, MonthCal_GetUnicodeFormat 함수는 wince에서는 동작하지 않는다. 이 두 함수의 선언 및 구현부는 {$ifdef win32} 지시자로 감싸둔다.

4. KOL의 TControl 기반의 달력 컨트롤을 생성할 수 있도록 다음과 같이 NewMonthCalendar 함수를 만들어 준다.

function WndProcMonthCalendarNotify( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
begin
  Result := false;
end;

function NewMonthCalendar( AParent: PControl): PControl;
const
  CS_OFF = {$ifdef win32}CS_OWNDC or CS_CLASSDC or {$endif}CS_PARENTDC or CS_GLOBALCLASS or
           CS_VREDRAW or CS_HREDRAW;
begin
  DoInitCommonControls( ICC_DATE_CLASSES );
  Result := _NewCommonControl( AParent, MONTHCAL_CLASS,
         WS_CHILD or WS_VISIBLE or WS_TABSTOP,
         TRUE,  nil );
  Result.SetSize( 191, 154 );
  Result.AttachProc( WndProcMonthCalendarNotify );
{$ifdef wince}
  Result.Perform(CCM_SETVERSION, COMCTL32_VERSION, 0);
{$endif wince}
end;



작업은 이것으로 끝. 달력을 생성해 폼 위에 올리는 코드는 다음과 같다.

TCalendarForm = ....
...
private
  fCalendar: PControl;
...

procedure TCalendarForm.KOLForm1FormCreate(Sender: PObj);
begin
  fCalendar := NewMonthCalendar(Form);
end;



달력에 날짜를 지정하거나 읽어올 때는 델파이에서 복사해 온 MonthCal_SetCurSel, MonthCal_GetCurSel 를 쓰면 편하다. 한가지, KOL의 SystemTime2DateTime은 델파이와 달리 1899년12월30일이 아닌 0년 0월 0일을 기준으로 한다. 아직 분석도 다 안끝났고 무엇보다 귀찮으니 그냥 SysUtils에 정의된 SystemTimeToDateTime() 을 쓰자.


function TCalendarForm.GetDateTime: TDateTime;
var
  pst: TSystemTime;
begin
  MonthCal_GetCurSel(fCalendar.Handle, pst);
  Result := SysUtils.SystemTimeToDateTime(pst);
end;

procedure TCalendarForm.SetDateTime(const AValue: TDateTime);
var
  pst: TSystemTime;
begin
  SysUtils.DateTimeToSystemTime(AValue, pst);
  MonthCal_SetCurSel(fCalendar.Handle, pst);
end;




폰트 크기를 50으로 주고 480*800 에뮬레이터에서 돌려본 화면은 짜잔~~ 멋지지 않은가!!







3월 23일 릴리즈 된 0.9.26.2 버전의 윈CE/LCL 인터페이스에 캘린더가 추가되었다고 한다.
그러나 이 팁은 KOL에서는 아직까지 유효하다~~ ^^

메모리 릭 체크하기

Lazarus

델파이의 빌드는 말 그대로 초스피드.
대부분의 델파이 프로그래머들은 이 엄청난 속도에 힘입어 코딩 후 즉각 실행시켜 확인하는 것이 습관처럼 되어있다. 게다가 FastMM이라는 걸출한 물건을 만난 이후부터는, 방금 만든 코드에 메모리 릭이 발생한다면 바로 바로 메시지를 띄워주기 때문에 별도의 프로파일러조차 필요없게 되었다.

그럼 라자루스는??

애석하게도 라자루스와 함께 사용할 메모리 릭 체커는 아직 찾지 못했다. 그러나 프리파스칼 컴파일러의 옵션에는 힙을 프로파일링하는 디버그옵션 "-gh"가 존재한다. 이 옵션을 잘 활용하면 FastMM만큼은 즉각적이지는 못해도 다른 도구의 도움 없이 흘린 메모리를 살펴볼 수 있게 된다.

먼저 fpc.cfg 파일을 열고 디버그 및 릴리즈 옵션을 다음과 같이 조절 한다.

#IFDEF RELEASE
  -O3
  -Xs
  -XX
#ENDIF

#IFDEF DEBUG
  -Crtoi
  -XS
  -glh
#ENDIF


-glh 는 줄단위 디버그정보와 위에서 언급한 힙 프로파일링 옵션을 켜 준다는 이야기이다. 나머지 옵션들은 fpc의 문서를 참조하자.

새 프로젝트를 생성하고 Project -> Compiler Options 메뉴에서 Other 페이지를 찾아가자.
여기에 컴파일러 지시자 -dDEBUG 를 다음과 같이 추가 해 준다.



(이렇게 개발중에는 컴파일러 지시자 -dDEBUG 를 주다가 실제 배포시에는 -dRELEASE 로 하는 것이 좋을 듯... )


프로파일된 결과물은 표준 출력으로 나오게 된다. 따라서 이 결과물을 보기 위해서는 실행파일이 콘솔을 가지고 있어야 한다. 메뉴에서 Project -> View Source 를 클릭해 *.lpr 제일 꼭대기에 다음과 같이 박아넣자.

{$ifdef DEBUG}
{$APPTYPE CONSOLE}
{$endif}


이제 프로젝트를 리빌드 한다. 한가지 문제가 있는데, 생성된 실행파일을 IDE에서 돌리는 것으로는 디버그 메시지가 표시되지 않는다는 것이다. 생성된 콘솔창이 프로그램 종료와 함께 닫혀버리기 때문이다. 따라서 커맨드 창을 띄우고 실행파일명을 직접 입력 해 주어야 한다.




프로그램을 종료하면 다음과 같이 사용된 메모리 정보가 표시된다.
뭐 아무짓도 안 했으니 메모리들이 모두 잘 반환되었다.



이제 Button1을 누를 때 마다 4바이트씩 메모리를 할당하도록 해 보자.

procedure TMainForm.Button1Click(Sender: PObj);
var
  i: PInteger;
begin
  New(i);
end;


버튼을 한 번 누르고 종료시킨 결과는 다음과 같다.




리소스릭이 발생한 유니트명과 함수명, 그리고 줄 번호까지 친절하게 표시 해 주고 있다. 만세~~!!


이 정보는 라자루스 포럼에 올라온 다음 두 개의 글타래를 종합한 것이다.

http://forum.lazarus.freepascal.org/index.php/topic,6121.0.html
http://forum.lazarus.freepascal.org/index.php/topic,5240.0.html



 

KOL-CE 2.80.3 릴리즈.

Lazarus/KOL-CE
간만에 소스포지에 가 봤더니 KOL-CE 2.80.3 버전이 나왔다. 2009년 1월 23일이면 연휴 바로 직전이군..
http://sourceforge.net/projects/kol-ce/

수정된 사항을 간단히 짚어보면,

* Enabled TTrayIcon for wince.
* Fixed compilation with FPC 2.2.3 and FPC 2.3.1. Patch by Carolos Foscolos.
* MCK: Fixed updating of source code in trunk version of Lazarus.
* MCK: Fixed code generation for new KOL application template, when form's unit name is renamed.
* MCK: Add InitCommonControls() call to fix themed control drawing if only standard controls are used.
* MCK: Fixed error "Restoring toolbar buttons bitmap from then previous version of the KOL&MCK format."  version of the KOL&MCK format."

이라는군. 아무튼 기쁜 소식이다~~!!!

이전 2.80.2 버전을 설치했던 경로는 /lazarus/userlib/kol-ce-2.80.2. 새 버전은 /lazarus/userlib/kol-ce-2.80.3 에 설치. (이거 누가 그랬을까~~ 누가 그랬을까!! 아마추어 같이~~ ㅠㅠ) 따라서 이전에 작업했던 프로젝트 파일 (*.lpi) 내의 경로들을 모두 수정 해 주어야 한다. 귀찮네... 다음번에 라자루스를 설치할 때는 그냥 lazarus/userlib/kol-ce 를 사용해야 겠다.

참고로 이 버전의 KOL-CE의 SIP메뉴 관련 수정 위치는 KOL.pas 의 33,847 라인이다.
매번 귀찮으니... 짧은 영어로라도 패치를 만들어 보내야 할 듯... ㅠㅠ;;

Pocket PC 2003 에뮬레이터 띄우기

Lazarus/Mobile

Embedded VC 4.0 을 받고 서팩4, 윈도 CE 5.0 및 PocketPC 2003 SDK를 설치하게 되면 시스템에 버추얼머신 우쩌구 하는 경고가 뜨면서 충돌예상 시스템이라 설치할 수 없다는 에러가 난다. 그 후 윈도 CE 5.0 에뮬은 잘 동작하지만 PPC2003 은 아래와 같은 경고가 발생하며 동작하지 않게 된다.




잘은 모르겠지만, 라자루스 위키에서 WM 5.0용 에뮬레이터를 깔 때 Virtual PC 2007을 설치하라고 말하는 것으로 보아... 무언가 예전과는 많이 바뀐 듯...

아무튼 이 에뮬레이터를 구동하는 단축키는 "C:\Program Files\Windows CE Tools\wce420\POCKET PC 2003\Emulation\emul.cmd" 를 실행시키게 되어있고 이 emul.cmd 의 내용은 다음과 같다.

start "" "C:\Program Files\Common Files\Microsoft Shared\Windows CE Tools\Platman\bin\PBEmulator.exe" /MemorySize 64 /Fastbackground /Skin "C:\Program Files\Windows CE Tools\wce420\POCKET PC 2003\Emulation\pocket_pc_emulator_skin.xml" /CEImage "C:\Program Files\Windows CE Tools\wce420\POCKET PC 2003\Emulation\PPC_2003_WWE.bin" /VMName "POCKET PC 2003 - POCKET PC 2003 Emulator" /HostKey 165


저 중간에 PBEmulator.exe 는 윈도 CE 3.0 에 대한 에뮬레이터였을 것이고... 그렇다면 이걸 지금 잘 동작하는 Emulator_500.exe로 바꿔보면 어떨까??

start "" "C:\Program Files\Common Files\Microsoft Shared\Windows CE Tools\Platman\bin\Emulator_500.exe" /MemorySize 64 /Fastbackground /Skin "C:\Program Files\Windows CE Tools\wce420\POCKET PC 2003\Emulation\pocket_pc_emulator_skin.xml" /CEImage "C:\Program Files\Windows CE Tools\wce420\POCKET PC 2003\Emulation\PPC_2003_WWE.bin" /VMName "POCKET PC 2003 - POCKET PC 2003 Emulator" /HostKey 165


결과는 대 성공!!! 잘 구동된다!!! 반갑다 Pocket PC 2003!!




뭐 당연한 이야기겠지만, CPU는 암 에뮬레이션이 아니라 인텔이다. 따라서 i386-wince 용으로 컴파일 한 프로그램만 구동될 것이다.




당분간 POZ 충전할 일은 없겠다. 캬캬캬~~~

MS에서 제공하는 해법도 있지만, 보안에 관계된 문제가 생길 수 있고 악성 코드에 감염될 수 있다는 경고가 붙어있다. 꼭 필요할 때만 수행하라고 하는데... 하지 않는 편이 좋을 듯...