2021년 11월 21일 일요일

델파이 11 버전으로 만들어진 윈도우32비트 실행파일을 윈도우XP에서 실행하기.

아직도 각종 기기를 제어하는 시스템에는 윈도우XP를 상당 사용하고 있습니다. (시스템 프로그램에 굳이 비용과 아이센스측면에서 윈도우7 이상을 사용할 이유는 없는 경우가 많습니다) 

iMac 에서 윈도우프로그램을 델파이로 만들어 실행파일을 돌려볼라치면 부트캠프를 사용하거나, 파라랠즈 같은 가상머신을 돌려서하는 방법이 있습니다. 

그런데 가상머신의 용량이 너무커서 부담이되어 패러럴즈에서 윈도우 XP를 설치하여 실험하면 좋겠다고 생각되어 XP를 설치하였습니다.

윈도우 10은 Lite버전을 설치한 후 델파이11 Alexandria 을 설치하였고,
윈도우 XP는 OS만 설치한후 용량입니다.

델파이11버전으로 윈32실행파일을 생성하여 XP에서 실행하려고 하면 "올바른 Win32응용 프로그램이 아닙니다"(아래)라는 경고창을 볼 수 있습니다.

구굴링해본 결과 델파이 11버전의 업그레이드버전에서는 문제가 해결되었다고 하네요.

업그레이드 이전 버전에서는 (수정. 2021.11 업그레이드 이후에도 아래와 같이 바꾸어주어야함)

 PE Header  부분을 6.0 에서 5.1로 수정하면 되더군요.



또는 프로젝트 소스에서 
program notepad_clone;
{$SETPEOSVERSION 5.1}     // 5.1 로 변경
{$SETPESUBSYSVERSION 5.1} // 5.1 로 변경 

만약 쓰레드를 사용하는 경우에는  Delphi 11 Windows XP compatibility tweak 을 참조하세요.

#delphi11 #windowsxp #windows32 #올바른 Win32 응용 프로그램 #delphi







2021년 11월 15일 월요일

iMac Big Sur 에서 윈도우98 설치하여 Delphi6.0을 설치하여 실행

 iMac Big Sur 에서 윈도우98 설치하여 Delphi6.0을 설치하여 실행하였습니다.

DOSBox-X 를 방문하시면 OS X (iMAC등)에서 윈도우98SE 설치방법을 알 수 있습니다.

참고로 위 홈피에서 언급하지 않은 사항만 알려드립니다.

DosBoox-X를 처음 실행하면 디렉토리를 지정하라고 합니다. 저는 문서폴더에 폴더를 하나만들어 지정하였습니다.(나중에 이미지 생성시 이곳에 생성되고, 델파이 .ISO 파일도 이곳에 둡니다)

도스박스 윈도우98 환경은 

/Users/jglee/Library/Preferences/DOSBox-X 0.83.19 Preferences

에 있으니 위 홈피에 나온 방법으로 수정하시면 됩니다.(반드시 수정하셔야  설치에 실수가 없습니다. 진짜 win98Se 정도의 속도 밖에 안나옴니다. 나중에 cpu 설정을 바꾸면 되겠지요)

DosBox-X를 압축해제 한 후 iMac의 Application 폴더로 복사/붙여넣기하신후 런처에서 실행하시면 됩니다.(런처에서 실행시 Preferences 설정환경으로 실행됩니다. Windows98SE 설치 참조)

DosBox-X 에서

IMGMAKE hdd.img -t hd_2gig
IMGMOUNT C hdd.img
IMGMOUNT D Win98.iso
IMGMOUNT A -bootcd D
BOOT A:

윈도우98 설치중 DosBox-X가 종료되면(실제 PC에서는 종료됩니다) 

아래와 같이 지정하고 재부팅하면 관련드라이버를 자동으로 잡습니다. (2회)

IMGMOUNT C hdd.img
IMGMOUNT D Win98.iso
BOOT C:

델파이6.0을 설치하려면 Borland Delphi 6.0 에서 다운 받은 후 압축해제 후 위에서 언급한 디렉토리에 저장하시면 됩니다.

IMGMOUNT C hdd.img
IMGMOUNT D Delphi60.iso
BOOT C:

2021년 11월 11일 목요일

MacOS 에서 Symbolic Link 만들기

MacOS 에서 Symbolic Link 만들기

Terminal 에서 "ln -s " command 를 사용하면 되지만,

Finder 에서 사용하려면..


(1) 아래 GitHub 사이트에서 SymLinker 앱을 다운 받아서 설치하고 수행시킨다.

다운로드

(2) Finder 에서 Services -> Make Symbolic Link 를 선택한다.


Xcode 13.1에서 iOS 10.3 App 생성시 'UIScene' is only available in iOS 13.0 or newer 에러 대처

 모처럼만에 XCode에 iPAD2 를 연결하여 빈화면을 생성하여 실행하려 하였더니.

'UIScene' is only available in iOS 13.0 or newer

가 발생되어 당황하였습니다. 검색결과.. 

SceneDelegate.swift 에서


@available(iOS 13.0, *) // (1)이것을 추가

class SceneDelegate: UIResponder, UIWindowSceneDelegate {



AppDelegate.swift 에서


class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow? // (2)이것을 추가


@available(iOS 13.0, *) // (3)이것을 추가

    func application(_ application: UIApplication, configurationForConnecting 


@available(iOS 13.0, *) // (4)이것을 추가

    func application(_ application: UIApplication,


해주면 되는군요.





2021년 10월 18일 월요일

델파이 소스를 간명하게 하기위한 방법중 하나

델파이 소스를 간명하게 하기위한 방법중 하나입니다.

필드영역에 보면 디자인 이후에 사용되지 않는 컨트롤이 잡다하게 있어 보기 싫을 경우가 있으면 해당 필드를 소스에서만 삭제하면 간명해집니다.  또다른 방법은 해당 콘트롤의 이름 속성을 오브젝트인스펙터에서 지워서 빈칸으로 하면 됩니다.

대신 삭제된 클라스를 ResisterClass()  로 등록해주면 됩니다.

아래 예제 그림 참조!





2021년 9월 17일 금요일

델파이 이전버전의 폼을 불러와 실행하면 스크린에 확대되어 보이는 경우가 있다.

 델파이 이전버전의 폼을 불러와 실행하면 스크린에 확대되어 보이는 경우가 있다.

아마도 아래와 같은 형태일 것이다.

 SnapBuffer = 5

  OnClose = FormClose

  OnCreate = FormCreate

  PixelsPerInch = 192

  DesignSize = (

    2733

    1783)

  TextHeight = 54


에서 처럼 PixelsPerInch = 192 로 되어 있다. 이것을 96으로 바꾸어 주자.

그렇기 위해서는 .DFM 파일을 텍스트로 변환하여야 한다.

델파이에서는 View as Text 가 안된다.

2021년 9월 13일 월요일

Delphi 11에서 RXLIB 2.7.5 사용하기

 Non offcial

다운로드 받은다음

rx.inc 파일 중간을

{$IFDEF VER350} { Embarcadero Delphi 11  }   // 
  {$DEFINE RX_D3}
  {$DEFINE RX_D4}
  {$DEFINE RX_D5}
  {$DEFINE RX_D6}
  {$DEFINE RX_D7}
  {$DEFINE RX_D9}
  {$DEFINE RX_D10}
  {$DEFINE RX_D11}
  {$DEFINE RX_D12}
  {$DEFINE RX_D14}
  {$DEFINE RX_D15}
  {$DEFINE RX_D16}
  {$DEFINE RX_D17}
  {$DEFINE RX_D18}
  {$DEFINE RX_D19}
  {$DEFINE RX_D20}
  {$DEFINE RX_D21}
  {$DEFINE RX_D22}
  {$DEFINE RX_D23}
  {$DEFINE RX_D24}
  {$DEFINE RX_D25}
  {$DEFINE RX_D26}
  {$DEFINE RX_D27} //Sydney specific
  {$DEFINE RX_D28} //Alexandria
{$ENDIF}

로 고치면 됩니다.


2021년 8월 7일 토요일

GarageBand 에 Komplete 사의 Kontrol M32를 연결하는 방법

 작곡과 반주를 공부하기위해 마스터키보드를 하나 구입했는데 막상 USB를 통하여 붙여보니 기본기능 밖에 하지 못해서 각종 스위치와 로브를 잘사용해보기위해 관련 설정을 해봅니다.

우선 Komplete 사에 접속하여 사용자등록을 합니다.

그림1

(1) 로그인하고,
그림2

 (2) Support 선택

그림3


(1) 다운로드를 선택

그림4


자신의 컴퓨터 종류에 맞게 (1) 또는 (2)를 다운받아 설치하고 실행(Native Access)합니다.

그림5
(1) 로그인하고, (2) 제품에 들어있는 Serial Number를 이용하여 등록하고 (3) Not installed를 선택합니다.

마스터키보드를 USB로 연결하고
그림6

(1) Komplete Kontrol을 설치합니다. 설치과정에서 마스터키보드가 꺼졌다 켜지면서 각종 디스플레이가 정상으로 표시됩니다.

그림7

GarageBand를
실행하고, (1) 소프트웨어 악기, (2) 생성을 선택합니다. 마스터 키보드 건반을 두드리면 소리를 들을 수 있습니다.  작곡또는 연주반주를 녹음하기위하여 마스터키보드의 왼쪽에 있는 12버튼중 Rec 버튼을 눌러봅니다. 아쉽게도 작동을 하지 않습니다. 
할 수 없이 마우스로 트랙에 이동하여, 트랙에서 오른쪽 크릭하고 미디영역을 생성하고 빨간 Rec 동그라미를 크릭해야겠지요.
그림8

(1) 트랙보기 버튼을 선택하고, (2) 플러그인을 선택하여

그림9


방금전에 설치한 Komplete Kontrol을 선택합니다. 그러면 아래와 같은 화면이 올라옵니다.
적당히 읽어 주시고...
그림10

그러면 마스터키보드의 오른쪽 위에 Plug-in MIDI 불이 들어옵니다.
그러나 아직도 연동이 안되네요. 더군다나 키보드를 눌러봐도 소리가 안나옵니다.

그림6의 (2)번을 선택하여 Mesine 2 Essential 을 설치합니다.
그러면 이러한 화면이 나오니 연결을 선택합니다.

그림11

이제 Metro나, Rec, Loop등의 버튼이 정상동작합니다.
그런데 건반을 눌러도 소리가 안나오네요...
새로운 트랙을 하나 추가해서 개러지밴드의 악기를 추가하거나,



그림9에서 프러그인을 다시 애플의 AUMIDISynsth로 지정해 줍니다.

개러지밴드를 종료하고 다시실행하면 그림11의 화면이 올라옵니다. (1) 연결을 선택하고 개러지밴드의 악기를 추가하면 프로그인 설정을 하지 않아도 됩니다.

첫번째 로브(볼륨)은 첫번째 트랙에 활당됩니다.
2번째 로브는 두번째 악기에 할당됩니다.
많은 도움이 되셨기를 바랍니다.






2021년 8월 5일 목요일

LibreCAD 무료 2D CAD 맛보기 - 1

   도학(제도?)에 쓸만한 가볍고 무료인 2D 캐드가 없나 찾던중 LibreCAD 라는 것을 찾아서 설치하여 도면을 그려보려 했더니 상당히 적응이 안되더군요. 너튜브에 자료가 있으나 별로도움이 안되고, 기본적인것 몇가지만 익히면 금방적응이 될것이라는 생각에 LibreCAD를 처음접하시는 분들에게 도움을 드리고자 배우면서 익힌것을 정리해 보렵니다.

윈도우, 맥, 리눅스에서도 된다고합니다. 저는 윈도우와 맥에 설치해서 이 강좌를 진행할까 합니다.

LibreCAD 를 통해 소스포지나 깃허브를 통해 다운받아 설치합니다. 


설치하고 처음나타나는 화면입니다.

그림1

리브레는 독과 툴바가 있는데 독을 상하좌우 플로팅위치의 것을 (1)에서 조절할 수 있습니다.  처음 이것을 못찾아서 프로그램을 헤멤, 나머지 툴바는 한번씩 눌러보면 그 의미를 쉽게 알 수 있습니다. 

선택된 툴바의 1개의 파라메터를 입력할 필요가 있을 때는 (2)에서 입력하면 됩니다. 파라메터가 2개 이상일 경우에는 Command: (오른쪽 하단에 있슴)에서 입력합니다.

나중에 툴바별로 적용하여 시험해 보겠습니다. 

(1)에서 왼쪽아이콘 을 크릭하면됩니다.  그림2와 같이 (1)번 독이 보이네요. 툴바를 풀어놓은 것입니다. 나중에 숙달되면 보이지 않게 해도 되겠지요. (별도 지정이 없으면 그림2를 기준으로 합니다)

그리고 Command Line 캡션바(화면 오른쪽 중간)를 드래그앤드롭하여 아래그림처럼 화면 아래쪽에 위치시키고 크기를 조절합니다.

하나의 화면에 본블러그 편집화면을 같이 쓰기위해 (5)독위치에서 오른쪽 독을 보이지않게 하였습니다.

그림2

(2)번은 스냅(자석=마우스로 위치지정할때)을 어떤기준으로 할 것 인가하는 것을 지정하는 것이고요, 

(3)번은 기준점을 [0, 0]으로 하거나, 현재의 위치를 기준점으로 바꾸어주는 것입니다.

(4)번은 줌기능인데 마우스 스크롤업다운으로 대신할수 있습니다. (4)번 문자 위의 버튼은  자동줌입니다.

그럼 큰 사각형 안에 모서리가 잘린 사각형을 그려보는 것으로 마무리를 해보겠습니다.

(5)에서 오른쪽 독이 보이게하고,  그림3의 Layer List에서 (1) +를 선택하여 레이어를 추가합니다.

그림3

그림3의 (2) 레이어 이름과 (3)선의 굵기를 선택한다음 (4)확인하여 레이어 추가를 완료합니다. 

그림 (2)에서 스냅온엔티티(Snap on entity)아이콘을 선택하고,  

(1)에서 사각형을 선택합니다.

(6) Specify first coner 에 0, 0 리턴합니다. 커서가 [0, 0]으로 옮겨갔네요.

계속하여 5000, 5000을 입력합니다.  (4) AutoZoom을 선택합니다.

이제 안쪽에 모서리가 잘린 사각형을 그려보겠습니다.

(1)에서 2 Points Line을 선택하고 Command 창에서 [1000, 4000], [4000, 4000]을 두번에 걸쳐서 입력합니다.
(1)에서 Vertical Line을 선택하고,  Length = -3000(화면 상단중앙 툴바에 있슴)을 입력하고, 화면상의 직선라인 오른쪽(+ 표시된곳)을 크릭합니다.
(1)에서 Horizontal Line을 선택하고, Length = -2000을 입력하고, 빨간(+)를 크릭합니다.
(1)에서 2 Points Line을 선택하고,  (2)에서 Restrict Vertical아이콘을 선택한다음, 빨간(+)를 크릭하고 마우스를 위쪽으로 드래그하여 적당한위치( 오토줌을 하였으면 위쪽 그리드)에서 크릭하면 수직선이 그려집니다.
(1)에서 2 Points Line을 선택하고, (2)에서 Restrict Horizontal아이콘을 선택한다음 빨간(+)를 크릭하고 왼쪽으로 드래그하여 크틱하면  수평선이 그려집니다.
(1)에서 2 Points Line을 선택하고, 빨간(+)를 크릭하고 마우스를 위쪽으로 드래그하고 크릭하면 수직선이 그려집니다.

이 예제만 익힌다면 다른 툴들은 같은 방법으로 사용할 수 있습니다. 


! 그런데 이도면은 .dxf와 .svc 로 저장이되고, Autocad에서 읽으니 못읽어 들이는 부분이 있네요... 









2021년 7월 28일 수요일

MAC 에서는 sketch, Windows에서는 Lunacy

 MAC 에서는 sketch  Windoes에서는 Lunacy를 사용하는것을 권장합니다.

Lunacy의 사용방법은 sketch와 거의 유사하더군요.

다만, 한글 폰트 사용이 잘 안된 다는 것입니다.

한글폰트를 지정했으나 실제 적용은 되지 않더군요.

이런방법으로 해결하였습니다.

윈도우10 최신버전에서 [제어판 > 국가 또는 지역 > 관리자 옵션 > 시스템 로갤변경 >지역설정] 에서 [현재 시스템 로갤은 그대로 두고, Beta:세계 언어 지원을 위해 Unicode UTF-8 사용을 체크]하여 주시고, 컴퓨터를 재부팅하면 상당한 시간(1분정도..)이 경과된후에 정상부팅이 됩니다. 이후에는 사용이 가능합니다. 



#Lunacy #Font #UTF-8 #Windows #Sketch

2021년 7월 24일 토요일

Mac Xcode에서 Python 3.9 사용하기

 일단은 Python 사이트에가서 dmg 파일을 다운받아 설치합니다.

m1 프로세서일경우에는 아래에 있는 파일이겠죠.
터미널을 열어 파이썬의 위치를 확인합니다.
파이썬3의 위치로 이동합니다.  [cd /usr/local/bin]
파인더를 엽니다. [open . ]
파인더에서 살펴보면 python3.9 가 있는데 Xcode에서 선택이 안되니...
링크(바로가기x)를 만듭니다. [ln python3.9 python39]

파인더를 닫지말고 열어둔 상태로 Xcode를 실행하고 
External Build System 프로젝트를 생성합니다.

프로젝트를 저장하고 위치를 기억합니다.
새로운 empty 파일을 하나 만들고 확장자를 .py로 합니다.
Xcode 메뉴 [Product > Scheme > EditScheme]을 실행하고 [Command + Shift + ,(<)]
Info Tab에서 Run(Debug) 항목의 Executable이 None으로 되어 있는 것을 영상과  바꾸어 줍니다.
[Executable > None > Other] 하고 방금전에 열어둔 파인더의 python39 파일을 열린창의 상단 Choose an executable to launch으로 드래그&드롭합니다.
python39 파일을 선택할 수 있게 됩니다. 선택합니다.
Debug executable은 선택제외하고, 
Option, Arguments Tab에서 영상과 같이 지정합니다.


콘솔창에서 확인합니다.


 


맥에서 스케치업 사용시 3D Text 안될때...

 맥에서 스케치업 사용시 3D Text 안되어서 원인을 알아본결과

맥 재 OS설치시 포맷할때 "APFS"로 되어있어야 하는데 "대소문자구분"로 하였더니 특정앱이 정상으로 작동하지 않았습니다.

스케치업의경우에 3D Text, instructor 등이 정상으로 작동되지 않았습니다.

mac sketchup instructor not showing

Text Tool not placing text






2021년 7월 23일 금요일

패러럴즈 네트워크 초기화 에러 대처법

Parallels 16: Network initialization failed.

Try this if you Parallels 16’s network not working on BigSur

1. sudo nano /Library/Preferences/Parallels/network.desktop.xml
2. find <UseKextless>1</UseKextless> (value can be -1), and change the value to the <UseKextless>0</UseKextless>
3. if you can’t to find this tag, then just create it under root tag <ParallelsNetworkConfig …>here</ParallelsNetworkConfig>

Result: you can start/restart Parallels without sudo – network will work.

주의할 것은 ~/Library 가 아니고 root   /Library 임에 주의!

이것을 알기전까지는 root로 로그인하여 실행하거나

sudo -b /Applications/Parallels\ Desktop.app/Contents/MacOS/prl_client_app 으로 실행함.

https://policeman0077.wordpress.com/2021/01/10/parallels-16-network-initialization-failed 에서가져옴.

2021년 7월 22일 목요일

swift vs delphi: 01

Swift를 공부하면서 Delphi를 재정립하자.

Structure

//Swift
struct Resolution {
var width = 0;
var height = 0;
}
let hd = Resolution(width: 1920, height: 1080)
var someResolution = Resolution(width: 640, height: 480) 

//Delphi
type
  TResolution = record
    width: integer;
    height: integer;
  end;
const
  hd: TResolution = (width: 1920; height: 1080);
var
  someResolution: TResolution = (width: 640; height: 480);

//Swift
  1. @propertyWrapper
  2. struct TwelveOrLess {
  3. private var number = 0
  4. var wrappedValue: Int {
  5. get { return number }
  6. set { number = min(newValue, 12) }
  7. }
  8. }

  9. //Delphi
  10. type TResolution = record private number : integer; function getWappedValue: integer; procedure setWappedValue(const Value: integer); property wrapValue: integer read number write number; property wrappedValue: integer read getWappedValue write setWappedValue; end;

  11. function TResolution.getWappedValue: integer;
  12. begin
  13.   Result:= number;
  14.   // willSet
  15. end;
  16. procedure TResolution.setWappedValue(const Value: integer);
  17. begin
  18.   if Value > 0 then
  19.     number:= Value
  20. else Value := 0;
  21.   // didSet
  22. end;


2021년 7월 21일 수요일

델파이 인터페이스

 델파이 인터페이스를 전혀 이해를 못하다가 Swift의 Protocol을 공부하면서 이해가 되었습니다. 물론 정확한지는 모르지만 제가 이해하는 수준입니다. 

이론적 배경은 구글링을 하시면 어렵게 설명되어 있으니 시스템프로그램하시는 분은 그곳을 참고하시고 저는 사용하는 입장에서만... 

Interface 가 도입된 배경은 Windows 32 시스템에서 COM을 사용하기 위한 것이고 지금은 COM을 사용하는 경우가 별로 없으니 GUID(Shift+Ctrl+G)는 생성할 필요는 없습니다.

먼저 다음과 같이 선언해보십시요.

type
  iCalc = interface
    function calcAdd(adx, bdx: integer): integer;
    function calcMulti(adx, bdx: integer): integer;
  end;
  TiCalc = class(TInterfacedObject, iCalc)
    function calcAdd(adx, bdx: integer): integer;
    function calcMulti(adx, bdx: integer): integer;
  end;
  jCalc = interface
    function calcSub(adx, bdx: integer): integer;
    function calcDivide(adx, bdx: integer): integer;
  end;
  TjCalc = class(TiCalc, iCalc, jCalc)
    function calcSub(adx, bdx: integer): integer;
    function calcDivide(adx, bdx: integer): integer;
  end;

구현은 Interface에서 하지 않고 Class에서 합니다.

TJCalc 가 다중상속되었슴에 주의하시면 되겠습니다. 

사용은 아래그림 및 아래와 같이하고


procedure TForm1.Button1Click(Sender: TObject);
var adx: iCalc;
begin
  adx:= TiCalc.Create;
  Label1.Caption:= adx.calcAdd(2, 3).ToString;
  //adx.free   Not need
end;
procedure TForm1.Button2Click(Sender: TObject);
var adx: jCalc;
begin
  adx:= TjCalc.Create;
  Label1.Caption:= adx.calcDivide(40, 2).ToString;
  //adx.free   Not need
end;
procedure TForm1.Button3Click(Sender: TObject);
var adx: iCalc;
begin
  adx:= TiCalc.Create;
  Label1.Caption:= adx.calcAdd(40, 2).ToString;
  //adx.free   Not need
end;

Button3에서는  TjCalc에서 구현하지 않은 상속받은 calcAdd 메소드를 사용했습에 주의하십시요.

결국 스위시의 프로토콜처럼 어떤 객체에 반드시 구현되어야 할(앞으로 사용 할 것임을 알리는?) 메소드를 먼저 선언한게 아닐까? 사용시에는 이것(Interface)만 보면 되겠지요.

 

2021년 7월 2일 금요일

Xcode 에서 command Line 실행파일위치

알고나면 아무것도 아닌데...

Xcode 에서 command Line 실행파일위치는?

즉, Swift , C ,C++ 등으로 생성한 실행파일의 위치는 어디인가?

나중에 터미널들에서 찾아가 실행하기위해서...

아래그림과 같이 찾아가면 됩니다.




해당 실행파일을 더블크릭하면 실행이되고, 
터미널에서 실행 할때는 통상 디렉토리까지 지정해주어야 실행됩니다.
필요하면 이전에 생성된 DerivedData 영역을 지워주면 좋을 것 같음. 

2021년 4월 28일 수요일

Delphi 10.4.2 TControlList 이해를 돕기위한 초간단 예제

델파이에서 애플의 테이블뷰를 구현 할 수 있게 되었습니다.

새로운 폼을 하나 만들고 ControlList를 alClient 로 올려놓고

ControlList 의 Item (prototype) 영역에 Label을 하나 올려 놓습니다.

간단하게하기위해 자료 컨테이너는 iMemo: TStringList 로 지정하고

아래 소스처럼 초기값을 넣습니다.

ComtrolList1.ItemHeight := 22;

procedure TForm2.ControlList1BeforeDrawItem(AIndex: Integer; ACanvas: TCanvas;
  ARect: TRect; AState: TOwnerDrawState);
begin
  Label1.Caption:= iMemo[Aindex];
end;
procedure TForm2.FormActivate(Sender: TObject);
begin
  iMemo:= TStringList.Create;
  iMemo.CommaText:= 'Hello, World,1,2,3,4,5,6,7,8,9';
  ControlList1.ItemCount:= iMemo.Count;
end;
procedure TForm2.FormDeactivate(Sender: TObject);
begin
  iMemo.Free;
end;

결과화면



 


2021년 3월 31일 수요일

Delphi 10.4.2 TControlList 예제

RAD스튜디오 10.4.2는 새로운 VCL 컨트롤들을 선보입니다. 그 중 TControlList는 매우 긴 리스트를 효과적으로 제어할 수 있는 컨트롤입니다. 현대식 룩앤필로, 원한다면 UI를 얼마든지 마음대로 설정할 수 있습니다.

파이어몽키의 ListView Item Designer와 닮은 TControlList는 리스트의 각 항목들을 대체해서(가상으로) 나타나는 리스트뷰 아이템의 레이아웃을 원하는 대로 만들 수 있습니다. 

TControlList는 단일 컬럼과 멀티 컬럼 레이아웃이 있는데, 원하는 형태를 선택할 수 있습니다. 완벽하게 가상화되어 있기 때문에 수천 혹은 수백만 개에 달하는 항목들도 얼마든지 제어 가능하며, 굉장히 빠른 스크롤이 가능합니다. 화면에 맞는 항목들만 표시할 수도 있습니다. 

그리고 High-DPI 옵션과 VCL 스타일을 지원할 뿐만 아니라 라이브바인딩(LiveBindings)도 완벽 지원합니다.

2021년 2월 2일 화요일

JSON 사용해보기 (Parsing)

 JSON의 이론적인 배경이 없이 사용하는데 참고가 될만한 사항만 정리 해봅니다.

동행복권을 REST로 읽어 보면 아래와 같은 구조입니다.

{"totSellamnt":100519459000,"returnValue":"success","drwNoDate":"2021-01-30","firstWinamnt":2188548716,"drwtNo6":41,"drwtNo4":31,"firstPrzwnerCo":11,"drwtNo5":38,"bnusNo":5,"firstAccumamnt":24074035876,"drwNo":948,"drwtNo2":18,"drwtNo3":30,"drwtNo1":13}

{} TJSONObject 
[] TJSONArray

"...." : 10051.. TJSONElement(Array 형태에서)
"...." : 10051   TJSONPair(Element 와 햇갈리죠)

"...." TJSONString
10051 TJSONValue

동행복권의 API는 단순하여 TJSONArray 가 없는 형태이다.

TJSONstring : TJSONValue 가 TJSONPair 가되는데 TJSONValue 자리에 TJSONObject, TJSONArray 가 올 수 있다.

TJASONObject 는 TJSONValue 형태와 TJASONText 형태로 우리가 볼 수 있다.

위의 형태가 TJSONValue 형태이고, 아래 형태가 TJSONText 형태이다.

{
   "totSellamnt":100519459000,
   "returnValue":"success",
   ..............
}


DELPHI의 RESTResponce 에는 이 2가지형태를 전부 제공해줍니다.
Var
  iJsonObject: TJSONObject;
  iJsonValue: TJSONValue;
선언해주고
iJsonObject := TJSONObject(RESTResponse1.JSONValue); 이와 같이 하여 가져옵니다.
Edit1.Text:= iJsonObject.ToJSON; 하면 위와 같은 형식으로 볼 수 있고
Memo1.Lines.Add( iJsonObject.ToString); 하면 2번째 형태로 보여줍니다.

예를 들어 bnusNo 의 값을 읽어오려면
iJsonValue := iJsonObject.Get('bnusNo').JSONValue; 와 같이 하면 되는데
TJsonValue는 TJSONObject가 될 수도 있고, string, number, boolean 이 될 수도 있다.
TJSONObject, , JSONString, TJSONNumber, TJSONPair, TJSONBool, TJSONArray

이렇게 알고 있는 형태로 변환하면서 읽어오면 됩니다.

물론 각각은 .Size 가 있어서 for var idx:= 0 iJsonValue.size -1 형태로 여러개의 Pair를 읽어 올 수도 있습니다.

다음에 기회되면 조금 복잡한 형태의 JSON을 읽어 Parsing 해보겠습니다.

2021년 1월 10일 일요일

리스트박스 값으로 소팅하기(ListBox, Value, Sort)

 리스트박스에 key=value 형태로 저장이 되어있을 때 Value 기준으로 소팅하고 싶으면,

문자데이터가 아니고 숫자데이터 일때

procedure TForm2.Button2Click(Sender: TObject);
var
  idx: Integer;
begin
  for idx := 0 to 30 do
    ListBox1.Items.AddPair(idx.ToString, IntToStr(Random(100)));
end;


// function TForm2.TStringsSort(List: TStringList; L, R: integer): integer;
// 이 아님에 주의!
function TStringsSort(List: TStringList; L, R: integer): integer;
begin
  Result:= StrToint(List.ValueFromIndex[L])-StrToInt(List.ValueFromIndex[R]);
end;


procedure TForm2.Button3Click(Sender: TObject);
var
  istrings: TStringList;
begin
  istrings:= TStringList.Create;
  try
    istrings.Assign(Listbox1.Items);
    istrings.CustomSort(@TStringsSort);
    Listbox1.Items.Assign(iStrings);
  finally
    istrings.Free;
  end;

2021년 1월 8일 금요일

Record를 담은 TList를 소팅하는 방법

TArray에서와 같은 방법으로 소팅하면 됩니다.

tBoll = record
    count: integer;
    name: string;
end; 
jTempArr: Tarray<tBoll>;
iList: TList<tBoll>
jBoll: tBoll;
iList := TList<TBoll>.Create;
SetLength(jTempArr, 45);
for idx := 0 to 44 do begin
      jTempArr[idx].Count := 0;
      jTempArr[idx].Name := BollName[idx];
 end;
 for idx := 0 to 44 do begin
        jBoll := jTempArr[idx];
        iList.Add(jBoll);
 end;
 iList.Sort(TComparer<TBoll>.Construct(
        function(const Left, Right: TBoll): integer begin
             Result := Left.Count - Right.Count;
             // Result:= CompareText(Left, Right);
        end));

와 같은 방법으로 하면 됩니다. 그냥 iList.sort 하였더니  숫자의 자리수가 다르거나  음수가 있으면 잘 안되더군요. 0, -99, 99 이렇게 되어있을 경우 0 이 가장적은 수가되버립니다.

잊어먹지 않기위해 정리하였습니다.  참고로 List 소팅도 정리합니다. (XE)

uses
  SysUtils, Generics.Defaults, Generics.Collections;
procedure Sort;
var
  List: TList<String>;
  AComparer: IComparer<string>;
  I: integer;
begin
  Randomize;
  AComparer:= TDelegatedComparer<string>.create(
    function(const Left, Right: String): integer begin
      Result:= StrToInt(Left) - StrToInt(Right);
    end);
  List:= TList<string>.Create(AComparer);
  for i := 0 to 9 do
    List.Add(IntToStr(Random(1000)));
  List.Sort;
  //  List.Sort(TComparer<string>.Construct(function(const left,right: string):integer begin
  //     Result:= StrToInt(Left)-StrToInt(Right); 
  //  end));
  for I := 0 to List.Count-1 do Writeln((List[i]));
  List.Free;
end;

2021년 1월 5일 화요일

레코드 형태의 행렬에서 검색하는 방법(TArray.BinarySearch)

type
  TBoll = record
    count: integer;
    name: string;
  end;
var     iArrayBoll: TArray<TBoll>;
procedure TForm1.Button2Click(Sender: TObject);
begin
  SetLength(iArrayBoll, Memo1.Lines.count);
  for var idx := low(iArrayBoll) to high(iArrayBoll) do begin
    iArrayBoll[idx].count := 25;
    iArrayBoll[idx].name := Memo1.Lines[idx];
  end;
  TArray.Sort<TBoll>(iArrayBoll, TComparer<TBoll>.Construct(
    function(const a, b: TBoll): integer begin
      // Result := StrToint(a.name) - StrToint(b.name); //숫자크기우선 정렬
      Result:= CompareText(a.name, b.name); //스트링 정상 정렬
    end));
  for var idx := low(iArrayBoll) to High(iArrayBoll) do begin
    Memo2.Lines.Add(iArrayBoll[idx].name + '=' + iArrayBoll[idx].count.ToString);
  end;
end;


procedure TForm1.Button4Click(Sender: TObject);
var
  idx: integer;
  iBoll: TBoll;
  Found: boolean;
begin
  if rbLineair.Checked then begin
    for idx := 0 to High(iArrayBoll) do
      if Edit1.Text = iArrayBoll[idx].name then begin
        Caption := intToStr(idx);
        Exit;
      end;
  end else begin
    iBoll.name := Edit1.Text;
    iBoll.count := 250;
    Found := TArray.BinarySearch<TBoll>(iArrayBoll, iBoll, idx, TDelegatedComparer<TBoll>.Construct(
      function(const a, b: TBoll): integer begin
        Result := CompareText(a.name, b.name);
      end));
    if Found then Caption := intToStr(idx) else Caption := 'No';
  end;
end;

사전에 정상 정렬되어 있지 않은 경우 아래처럼 오류가 나온다. BinarySearch 전에 스트링의 경우 정상 정렬(숫자크기우선 정렬이면 안됨)이되어 있어야 한다. 이것 때문에 두어시간 해메었었네요.

레코드 형태의 행렬을 소팅하는 방법(별거아닌데 예제가 귀해서...)

 TArray<integer>나, Tarray<string> 으로 되어 있느 배열은 Tarray.sort<integer>(iArray) 과 같은 방법으로 할수 있습니다.

procedure TForm1.Button1Click(Sender: TObject);
var     iArray: TArray<string>;
begin
  SetLength(iArray, Memo1.Lines.count);
  iArray := Memo1.Lines.ToStringArray;
  TArray.Sort<string>(iArray);
  Memo2.Lines.AddStrings(iArray);
end;

유사한 방법으로 레코드 형태의 배열이며 특정 필드로 소팅한다면

  TBoll = record
    count: integer;
    name: string;
  end;
procedure TForm1.Button2Click(Sender: TObject);
var     iArrayBoll: TArray<TBoll>;
begin
  SetLength(iArrayBoll, Memo1.Lines.count);
  for var idx := low(iArrayBoll) to high(iArrayBoll) do begin
    iArrayBoll[idx].count := 0;
    iArrayBoll[idx].name := Memo1.Lines[idx];
  end;
  TArray.Sort<TBoll>(iArrayBoll, TComparer<TBoll>.Construct(
    function(const a, b: TBoll): integer
    begin
      Result := StrToint(a.name)- StrToInt(b.name); 
     //string 의 경우에는 Result:= CompareText(a.name, b.name);
    end));
  for var idx := low(iArrayBoll) to High(iArrayBoll) do begin
    Memo2.Lines.Add(iArrayBoll[idx].name);
  end;
end;

검색은

procedure TForm1.Button3Click(Sender: TObject);

var
  iStr: string;
  idx: integer;
begin
  iStr := Edit1.Text;
  if Tarray.BinarySearch<string>(iArray, iStr, idx) then Button3.Caption:= intToStr(idx);
end;

델파이 12.1이냐 11.3이냐?

 델파이가 12.1이 나왔습니다. 혹시 11.3버전의 커뮤니티버전이 필요하시는분이 있을 수 있을 것 같아 https://altd.embarcadero.com/.../RADStudio_11_3_esd_28... 와 이것 찾느랴 엄청고생함.