Palm Work Book UserPreferences
 
Help Info Print View Search Diffs Edit
 인덱스   찾기   Freeboard   Subjectless   Images   최근글 

See also PalmProgramming

  1. 2002년 11월
  2. 2002년 10월
  3. 2002년 9월
  4. 2002년 8월
  5. 2002년 7월
  6. 2002년 6월
  7. 2002년 5월

2002년 11월

delete 구문을
MemPtrFree?()
함수로 바꾼 것만으로 버그 소멸. [...]

저수준의 힘. 놀랍도다...

...

Lightweight C++ Framework for PalmOS. 팁.

Palm 프로그래밍에서는 화면에 보이는 모든 리소스(폼 컨트롤)에 대해 그 해당 리소스의 struct가 존재하지 않는다. 예를 들면 Field같은 경우는 FieldType?이라는 구조체가 존재하지만, Label의 경우에는 LabelType?이라는 구조체는 존재하지 않는다. 대신, ControlType?이라고 하는 상위의 구조체가 존재한다. (FieldType? 구조체도 일부는 ControlType? 구조체로 캐스팅해서 '일부'는 사용할 수 있다. 즉, ControlType? 구조체는 FieldType?의 상위 구조체)

Lightweight C++ Framework for PalmOS(이하 FW)에서는 폼 컨트롤에 대해 Wrapper 클래스를 제공하고 있다 : List, Field 클래스가 제공되며, (이 두 컨트롤의 이용이 가장 난해하기 때문인 듯) Widget이라는 상위 클래스를 갖는다.

하지만, List, Field 컨트롤 이외의 것들도 사용할 수 있도록 Form 클래스에서 지원하고 있다. 다음과 같은 방법으로 사용한다 :
    // 이런 폼이 존재할 때..
    AgentEditForm? *f = (AgentEditForm?*)(Application::Instance())->GetForm?(AgentEditFormForm?);

    // 컨트롤의 비활성화
    f->EnableControl?(AgentEditFormUseEncryptionCheckbox?, False)
    // Label, Trigger.. 등 레이블이 있는 컨트롤의 경우 레이블을 지정
    f->SetLabelText?(AgentEditFormPasswordSelTrigger?,"--Assigned--");
    // 체크박스 Check
    f->SetCheckBox?(AgentEditFormUseEncryptionCheckbox?, True);

    그 외에도 HideControl?(), ShowControl?(), IsCheckBoxSet?(), DrawControl?(), SetControlLabel?() 등이 있다.

2002년 10월

Graham Wheeler의 경량 C++ 프레임워크 for 팜OS를 사용하려 노력중.
(
http://www.bradygirl.com/PalmFW/index.html 참고URL)
뭐.. 유용하기는 하겠다만..
얼만큼 옮겨서 사용할 수 있을지는. 솔직히 의문.

2002년 9월

USB to IrDA 모듈을 이용해서 인터넷 가능해짐.

You win -_-d


아악...!
클리에 T650C는 USB라서리... ppp 접속을 할 수가 없다.
때마침 노트북도 없어서 IR 통신 ppp도 불가능하다. -_-;

도대체 클리에를 왜 공수해온거시야? -_-

...

클리에의 HR(HiRes?, 고해상도) 관련 API 사용시, 기존 API와 호환되거나, 그렇지 않은 것들이 많다.

현재 N700 에뮬에서 테스트한 결과는 :

저해상도 비트맵의 소스 데이터를 현재 폼 윈도우에(비트맵 소스의 주소값을 알아내서) 칠해버린다.
문제의 소지가 있는 것으로 보이지만, 아직까지는 정상적으로-겉으로 보기에는-동작하고 있다.

2002년 8월

BMP 생성 및 가상 윈도우에서 내용 옮기기
    WinHandle? hWndScreen?,oldDrawWin?H;
    UInt16 error;
    BmpType?* pBmpScreen?

    oldDrawWin?H = WinGetDrawWindow?();

    pBmpScreen? = BmpCreate?(160,160,8,NULL,&error);
    if(pBmpScreen?)
    {

      hWndScreen? = WinCreateBitmapWindow?(pBmpScreen?, &error);
      if(hWndScreen?)
      {
        WinSetDrawWindow?(hWndScreen?);
        WinSetForeColor?(BLACK);
        WinDrawLine?(0,0,10,10);
        WinDrawLine?(10,10,20,20);
        WinSetForeColor?(WHITE);
        WinDrawLine?(10,10,0,0);
        WinDrawLine?(20,20,10,10);
      }
    }
    WinSetDrawWindow?(oldDrawWin?H); // 원래 윈도우 핸들 설정으로 돌아옴
    WinSetDrawMode?(winPaint);

    WinDrawBitmap?(pBmpScreen?,0,0); // 실제 비트맵을 그려주는 코드

    WinDeleteWindow?(hWndScreen?, true);
    hWndScreen? = NULL;
    delete pBmpScreen?;
    pBmpScreen? = NULL;

}
---
현재 기기의 사용자이름 알아내기(HotSync
?시 식별용도로도 사용)
    Char szUserName?[32];
    DlkGetSyncInfo? (NULL, NULL, NULL, szUserName?, NULL, NULL);

모달폼 제대로 사용하기
    FormPtr? previousForm = FrmGetActiveForm?();
    FormPtr? frm = FrmInitForm?(ID_PASSWORD);
    UInt16 hitButton;
    FieldPtr? fieldPtr;
    MemHandle? passwdH;

    FrmSetActiveForm?(frm);
    FrmSetEventHandler?(frm, PasswordFormHandleEvent?);

    /* Set default password to blank */
    fieldPtr = FrmGetObjectPtr? (frm, FrmGetObjectIndex? (frm, ID_PASSWORD_PASSWORD));
    passwdH = MemHandleNew? (maxlength);
    MemMove? (MemHandleLock? (passwdH), "\0", 1);
    MemHandleUnlock? (passwdH);
    FldSetTextHandle? (fieldPtr, (Handle)passwdH);
    FrmSetFocus?(frm, FrmGetObjectIndex?(frm, ID_PASSWORD_PASSWORD));

    hitButton = FrmDoDialog?(frm);

    if (hitButton == ID_PASSWORD_OK)
    {

      MemSet? (password, maxlength, 0);
      if ((FldGetTextPtr? (fieldPtr) != NULL) && ((StrLen? (FldGetTextPtr? (fieldPtr)) + 1) < maxlength))
        MemMove? (password, FldGetTextPtr? (fieldPtr), StrLen? (FldGetTextPtr? (fieldPtr)) + 1);
      else
        hitButton = ID_PASSWORD_CANCEL;
    }

    if (previousForm)

      FrmSetActiveForm?(previousForm);
    FrmDeleteForm?(frm);

    return (hitButton == ID_PASSWORD_OK);


컨트롤을 폼에서 감추기/보여주기
    FrmHideObject?(frmP,FrmGetObjectIndex?(frmP,PreferencesNamingPortField?));
    FrmShowObject?(frmP,FrmGetObjectIndex?(frmP,PreferencesNamingPortField?));
몇가지 방법이 더 있을 수 있으나, 어떤 컨트롤에도 적용할 수 있다는 점에서 좋다.

PopTrigger?를 클릭해서 다른 필드를 선택해도, Label의 내용이 자동으로 바뀌지 않으므로 바꾸는 코드를 넣어줘야 한다. popSelectEvent?를 받자.

모달 폼을 모달리스처럼 사용하기
    메뉴, 혹은 버튼이 클릭되었을 때 FrmGotoForm?(FORM_ID)로 폼으로 이동
    AppHandleEvent?에서 frmLoadEvent?가 발생하게 되므로, FrmInitForm?, FrmSetActiveForm?을 호출한다.
    FrmSetEventHandler?(frmP, PreferencesFormHandleEvent?); 로 해당 폼에 이벤트 핸들러를 할당.
    그런 다음 특정 버튼의 이벤트에 FrmGotoForm?(MainForm?)를 할당하고, frmCloseEvent?시 FrmEraseForm?(frmP); FrmDeleteForm?(frmP);를 호출.
    이러면 메모리의 낭비없이(물론 메인폼은 계속 메모리에 남아 있지만..) 다른 폼을 호출했다가 지울 수 있다.
    물론 버튼이 OK/Cancel뿐일때는 그냥 FrmDoDialog?()를 쓰는게 좋다.

필드에 값 쌔려넣기 최종판
    FieldType?* field;
    Char* dest;
    Char tempNum[5];
    Handle handle, oldHandle;
    GetObjectPtr?(field, FieldID);
    oldHandle = FldGetTextHandle?(field); // get the current text handle
    if(oldHandle)
    {
      FldSetTextHandle?(field,NULL); // release this handle from field
      MemHandleFree?(oldHandle);
    }
    StrIToA(tempNum, num);
    handle = MemHandleNew?(strlen(tempNum)+1);
    dest = (Char*)MemHandleLock?(handle);
      strcpy(dest, tempNum);
      MemHandleUnlock?(handle);
    FldSetTextHandle?(field,handle);
위와 같이 한 다음, frmCloseEvent?를 받을 때 각 필드에 FldFreeMemory?()를 호출한다 :
    FieldType? *pField;
    GetObjectPtr?(pField, PreferencesNamingPortField?);
    FldFreeMemory?(pField);


sleep()은 초단위다. ms가 아니다. [...]


함부로 리소스 위치를 바꾸지 말지어다...
    if (eventP->eType == frmLoadEvent?)
    {
      // Load the form resource.
      formId = eventP->data.frmLoad.formID;
      frmP = FrmGetFormPtr?(formId);
        if (frmP == 0)
        frmP = FrmInitForm?(formId);
      FrmSetActiveForm?(frmP);
위 코드는 폼을 로드할 때 쓰는 것인데, 이유없이 FrmInitForm?에서 NULL Handle이란 에러가 뻑뻑 나면 틀림없이 리소스를 제대로 읽어들이지 못하는 것이므로... 리소스 헤더 파일의 위치가 Rsc 폴더에 있는지 확인하고, 프로젝트에 포함된 rsrc 파일의 경로도 확인해본다. (히든폴더 안에 있는게 연결되어 있으면 조땐거시다)

2002년 7월

개발툴을 CodeWarrior R8(update to 8.3)으로 변경하다.


집 컴터는 찐따되고.. 웹서버는 맛이가고..
짜증이 솟구치는 플밍의 일상속에 -_-

에러287개워닝66개의소스코드를눈앞에둔코더의뇌리에조또라는단어가스쳐간다.

코더여 신화가 되어라.


GCC 최고의 잡질...

어제의 교훈 - 엄하게 프로그램 이름을 바꾸려다간 조때는 수가 있다 :
단지 Helloworld를 TelnetTest?로 바꿨다가
프로그램 크기가 12배(32KB -> 390KB)로 늘어나는
황당한 경험을 함. -_-
(참고로, PalmOS 3.5에서, 64KB(65505) 이상의 코드는 로드 자체가 불가능하다.


커넥션이 끊겼을 때... 제대로 잡히는건가? 뭐가 어떻게 된건지 원... -_-a ;;


일단 CClientSocket? 들어가긴 했는데...
스레드 관련 처리가 골때리는군... 큰일이다 -_-;;
대강 고쳐놓고 스레드 처리 부분은 천천히 생각해봐야겠다...

...

일단 CClientSocket?은 RFB 프로토콜 관련 부분이 여러가지로 피곤하게 되어 있으니. -_- 잠시 보류.
std 라이브러리라도 사용 가능하게 돼야 뭘 어케 할 수 있을 듯.

CListenSocket?은 Accept했을 때...
새로운 소켓(CClientSocket?)을 생성한 후에 처음 소켓의 설정을 해주는 부분... 과.
소켓의 리스트를 생성해서 각 소켓에게 실행 시간을 할당하는 부분을 만들어야 하겠다...

지금 아이디어로는, 일단 처음부터 리스트를 생성해서
리스트의 처음에 기본 소켓을 넣고 (리슨이든 클라이언트든) m_bSocketRunning?은 false 상태에서
뭔가 액세스가 들어오거나, 연결하거나, 그때부터 소켓을 추가해서
각 소켓에 실행 시간을 할당하는 부분을 만들어야 할 것 같다.
m_bEnd는 사용해야만 할 것 같다... 결국.
소켓이 작동하는지의 여부만으로는 언제 소켓을 죽여야할지 알 수 없으니까.

자. 자.. 일단은 프로토타입을 목표로.


아래 문장... 의도한대로 될까 안될까? 깊게 생각해봐라. 포인터도 결국은 변수다.
MoveNext?(pNode);
...
void MoveNext?(Node *pNode)
{ pNode = pNode->m_pNext; }

삽질에 삽질의 연속.

역시 처음에 제대로 동작하는 넘부터 보고 나서 프로그램을 짜야한다. -_-

어쨌거나, 치명적인 에러는 잡았으니..
에러났을때 Reject 때려주는 부분이 문제가 되는건가.

로직은 저녁 먹구 와서 잡아야지. 랄라라... -_-;


..결국은 리스트를 만들다..

노드에 해당하는 클래스와, 리스트에 해당하는 클래스를 맹글었다. (CXStreamDataNode?, CXObList?)
나중에 void*를 지원하는 클래스로 만들기로 하고, 지금은 일단 그냥 쓰기로해따.


현재 팜용 stl 라이브러리를 찾는 중.
... 정 안되면 List정도는 내가 직접 구현해야 할 것 같은데... ㅡㅡ

하아..

MSL이라는 물건이 있어서...
이걸 쓰면 일단은 기본적인 라이브러리는 사용가능한듯 한데(IOStream.h 따위라든가)
CodeWarrior용 라이브러리다. [...]
GCC에서는 사용이 불가능한 듯 싶으므로. 일단 탈락.

HP 산하 연구소넘들이 맹글었다는 STL 라이브러리를 가져다가 쓸까 하는데..
list.h를 인클루드했더니. 이런.
Palm SDK에 list.h란 이름을 가진 헤더파일이 이미 있기 때문에.. 충돌한다. -_-;
일단은 이름 바꿔서라도 죄다 인클루드를 해볼까 말까... 고민중. 삽질하는거가따.

휴일의 보람찬 삽질. -_- 뭐 그래도 씨디굽고 회화테입옮기는건 했으니까 ;


메모리 핸들 사용시의 주의점 :
PalmOS에서 메모리는 chunk라는 단위로 할당받게 되는데, 이는 Movable, 혹은 Non-Movable로 나뉘게 된다.
또한, 할당받은 chunk는 lock을 걸어야 사용이 가능하고, unlock으로 해제해 주어야
나중에 free로 chunk를 OS에 되돌려 줄 수 있게 된다.
Handle handle;
// 10바이트 크기의 Movable chunk(=heap)의 핸들을 반환한다.
handle = MemHandleNew?(10); Char* szTemp;
// 핸들의 Lock count++(핸들을 잠근다) 해당 메모리 handle의 포인터를 반환한다. (Non-Movable)
szTemp = (Char*)MemHandleLock?(handle);
// MemHandleUnlock?(handle)도 되지만, Unlock을 두번하면 에러가 발생한다 (lock count==0일때는 Unlock할 수 없다.)
MemPtrUnlock?(szTemp);
// 메모리 핸들을 무효화하고 해당 chunk를 OS에 반환한다. MemPtrFree?(szTemp)도 가능할까?... 해봐라.
MemHandleFree?(Handle);

아래의 코드에서 Under-locked 에러 해결중. (에뮬에서는 정상 작동함...)
-> POSE에서 에러 핸들링 옵션이 켜져있는지 항상 확인. 확인. 정상 작동하긴. 개뿔이나 -_-

////////////////////////////////////
//수정 버전
    if(strlen(buffer) > 0)
    {
      FieldPtr? field;
      Char* dest;
      Handle handle, oldHandle;
      field = (FieldPtr?) FrmGetObjectPtr?(FrmGetActiveForm?(), FrmGetObjectIndex?(FrmGetActiveForm?(), ID_MAIN_MESSAGEWINDOW));
      oldHandle = FldGetTextHandle?(field); // get the current text handle
      FldSetTextHandle?(field,NULL); // release this handle from field

      handle = MemHandleNew?(strlen(buffer)+1);
      dest = (Char*)MemHandleLock?(handle);
      strcpy(dest, buffer);
      FldSetTextHandle?(field,handle);

      FldDrawField?(field);
      oldHandle = FldGetTextHandle?(field); // get the current text handle
      FldSetTextHandle?(field,NULL); // release this handle from field

      MemPtrUnlock?(dest);
      //MemHandleUnlock?(handle); 포인터로 받은 Non-Movable 영역을 해제했으므로, 따로 할 필요가 없다.
      if(oldHandle)
      {

        MemHandleFree?(oldHandle);
      }
    }


2002년 6월

////////////////////////////////////////////
// 메모리 누출 없이 필드에 출력하는 루틴
    Char buffer[1024];
    Int16 nBufferLen?;
    nBufferLen? = Receive(buffer,1024);
    //////////////////////////////////////
    // 메시지창에 출력하는 루틴
    if(strlen(buffer) > 0)
    {
      FieldPtr? field;
      Char* dest;
      Handle handle, oldHandle;
      field = (FieldPtr?) FrmGetObjectPtr?(FrmGetActiveForm?(), FrmGetObjectIndex?(FrmGetActiveForm?(), ID_MAIN_MESSAGEWINDOW));

      handle = MemHandleNew?(strlen(buffer)+1);
      dest = (Char*)MemHandleLock?(handle);
      strcpy(dest, buffer);

      FldSetTextHandle?(field,handle);

      FldDrawField?(field);
      oldHandle = FldGetTextHandle?(field); // get the current text handle
      FldSetTextHandle?(field,NULL); // release this handle from field

      MemPtrUnlock?(dest);
      MemHandleUnlock?(handle);

      if(oldHandle)
      {

        MemHandleFree?(oldHandle);
      }
    }


ProcessEvent?()의 작성 완료. select()를 이용한 Exception은 처리되지 않음. (PalmOS에서 지원하지 않음)
CClientSocket?, CListenSocket?, CXStreamBuffer?(+CXStreamData?) 클래스의 파일들 추가, 컨버전 시작

setsockopt()로 Non-Blocking 모드를 지정할 수 없다.
Except for the netSocketOptSockNonBlocking? option, all
options listed above have equivalents in the sockets API. The
netSocketOptSockNonBlocking? option was added to this call
in the net library in order to implement the functionality of the
UNIX fcntl() control call, which can be used to turn nonblocking
mode on and off for sockets.


Palm 네트웍 프로그래밍시 주의사항 :

// 전역 변수
Err errno;
Int32 AppNetTimeout?;
Char AppINETString[16];
NetHostInfoBufType? AppHostInfo?;
NetServInfoBufType? AppServInfo?;
UInt16 AppNetRefnum?;
Err h_errno;
CPalmXSocket 기본 메서드의 동작 확인. 어쨌든 메시지는 뱉고 받는건 된다!

NetLibSysFind? (맞나?) -> NetLibOpen? -> NetLibSocketOpen? -> ... -> NetLibSocketClose? -> NetLibClose?
간단한 소켓 프로그래밍은 위와 같은 함수를 사용해서 할 수 있다.
(위의 함수 중 하나라도 누락되면 정상적인 프로그래밍이 불가능하다!)


Palm 네트웍 소켓 프로그래밍에서 대응되는 타입

socket(int) - NetSocketRef?
sockaddr(struct *void) - NetSocketAddrType?
domain(int) - NetSocketAddrEnum?
TCP/UDP type(int) - NetSocketTypeEnum?
protocol(int) - Int16
sockaddr_in(struct *void) - NetSocketAddr?INType

system/sys_socket.h 파일에 Berkeley Socket API가 정의되어 있다.
(일부는 원래 함수의 원형으로 동작하고, 그렇지 않은 것도 있다.)

CXSocket -> CPalmXSocket으로 컨버젼 시작.


Palm 프로그래밍에서 사용하는 타입들
Development Tools Guide p.383 참고(Int16, UInt32.. 같은 형식. 핸들도 참고)

네트웍 관련(Berkeley Socket API) : Palm OS Companion2.pds p.144 참고


    EvtGetEvent?(&e, eventTimeout); // 큐에 존재하는 다음 이벤트를 가져온다.

    // we capture the DateBook? and PhoneBook? keys to emulate
    // the second and the third mouse buttons
    passSystem = e.eType == keyDownEvent? &&
      (e.data.keyDown.chr == hard1Chr ||
        e.data.keyDown.chr == hard2Chr ||
        e.data.keyDown.chr == hard3Chr ||
        e.data.keyDown.chr == hard4Chr ||
        e.data.keyDown.chr == pageUpChr? ||
        e.data.keyDown.chr == pageDownChr? ||
        e.data.keyDown.chr == vchrKeyboard ||
        e.data.keyDown.chr == vchrKeyboardAlpha? ||
        e.data.keyDown.chr == vchrKeyboardNumeric?) ;

    if (passSystem) {
      if (!ApplicationHandleEvent? (&e))
    FrmDispatchEvent? (&e);
    }
위와 같은 코드를 사용함으로써 DateBook?, PhoneBook? 버튼 등을 눌렀을 때 프로그램으로 이벤트를 돌릴 수 있다.
원래 이벤트는 다음과 같이 처리된다 :
    if (!SysHandleEvent? (&e))
      if (!MenuHandleEvent? (NULL, &e, &err))
        if (!ApplicationHandleEvent? (&e))
          FrmDispatchEvent? (&e);
FD_ZERO, FD_SET 매크로의 용도는?

현재 표시중인 화면을 나타내는 구조체 :
/* defines boudaries of the Pilot viewport */
typedef struct {
    rfbRectangle desktop; // Dimensions of unscaled desktop
    unsigned short scaleFactor; // Scale factor for current viewport
    rfbRectangle viewable; // what is visible
    rfbRectangle virtual; // what is in the off-screen window
    rfbRectangle remote; // what is on the server side
    rfbRectangle zoomarea; // specified zoom coordinates
    Boolean zoomarea_ena; // Use specified zoom coordinates
} PRFBViewport;

NetLibSend? ; Purpose Send data to a socket from a single buffer.
Int16 NetLibSend? (UInt16 libRefNum?, NetSocketRef? socket, void *bufP, UInt16 bufLen,
UInt16 flags, void *toAddrP, UInt16 toLen, Int32 timeout, Err *errP)
-> libRefNum? Reference number of the net library.
-> socket Descriptor for the open socket.
-> bufP Pointer to data to write.
-> bufLen Length of data to write
-> flags One or more netIOFlagxxx flags. See “I/O Flags.”
-> toAddrP Address to send to (a pointer to a NetSocketAddrType?), or 0.
-> toLen Size of toAddrP buffer.
-> timeout Maximum timeout in system ticks; -1 means wait forever.
<- errP Contains an error code if the return value is -1.

Returns the number of bytes successfully sent. Returns 0 if the
socket has been shut down by the remote host. If the return value is
-1, an error has occurred, and errP contains one of the following
values:
0 No error.
netErrTimeout? Call timed out.
netErrNotOpen? The referenced net library has not been opened
yet.
netErrParamErr?
netErrSocketNotOpen?
netErrMessageTooBig?
netErrSocketNotConnected?
netErrSocketClosedByRemote?
netErrIPCantFragment?
netErrIPNoRoute?
netErrIPNoSrc?
netErrIPNoDst?
netErrIPktOverflow?
netErrOutOfCmdBlocks?
netErrOutOfPackets?
netErrInterfaceNotFound?
netErrInterfaceDown?
netErrUnreachableDest?
netErrNoMultiPktAddr?
netErrWouldBlock?

Sockets Equivalent
int sendto (int socket, const void *bufP,
int bufLen, int flags, const void *toAddrP,
int toLen);
int send (int socket, const void *bufP,
int bufLen, int flags);
int write (int socket, const void *bufP,
int bufLen,);

Comments
This call attempts to write data to the specified socket and returns
the number of bytes actually sent, which may be less than or equal
to the requested number of bytes. The data is passed in a single
buffer that bufP points to.
For datagram sockets, you must only send a single packet at a time.
If the data is too large to fit in a single UDP packet (1536 bytes), no
data is sent and -1 is returned.
The toAddrP field applies only to datagram sockets without an
existing connection. An error is returned if the datagram socket was
previously connected and toAddrP is specified. Stream-based
sockets, by definition, must have a connection established with a
remote host before data can be written. Raw sockets (supported in
Palm OS version 3.0 and higher) must construct the entire IP header,
including the destination address, before data can be sent; thus, the
address is taken from the data to be sent.
If there isn’t enough buffer space to send any data, this call will
block until there is enough buffer space, or until a timeout.

NOTE: For stream-based sockets, this call may write only a
portion of the desired data. It always returns the number of bytes
actually written. Consequently, the caller should be prepared to
call this routine repeatedly until the desired number of bytes have
been written, or until it returns 0 or -1.


특정 폼에 대해 이벤트 핸들러 콜백 루틴을 설정한다.
formP ; Pointer to the form object (FormType? structure).
handler ; Address of the form event handler function, FormEventHandler?.

폼이 여러개일 때에 이벤트 핸들을 할당하는 방식 ;

    if (e->eType == frmLoadEvent?)
    {
      formId = e->data.frmLoad.formID;
      frm = FrmInitForm? (formId);
      FrmSetActiveForm? (frm);

      switch(formId)
      {

        case ID_MAIN:
          FrmSetEventHandler?(frm, MainFormHandleEvent?);
          break;
          ...
MainFormHandleEvent?를 할당한다. 만약 넘겨받은 formID가 명시된 것이 아닐 경우(frmOpenEvent?,
frmLoadEvent?를 사용하는 경우 등..) frmDispatchEvent?로 이벤트를 현재 폼의 이벤트 핸들러에
넘겨준다.

RGB 관련/팔레트, 컬러 윈도우 시스템에 관련된 것은 3.5 이상에서 사용 가능.

Err WinPalette? (UInt8 operation, Int16 startIndex, UInt16 paletteEntries, RGBColorType? *tableP)
현재의 윈도우 팔레트를 설정/가져오거나 디폴트 값 설정하는 명령(V3.5 이상)

SysLibFind? ; 시스템에 이미 로드되어 있는 라이브러리를 찾음. 대부분의 라이브러리(NetLib?,Serial,IR)은
리셋되면 자동으로 로드되기 때문에, 기타 라이브러리는 SysLibLoad?를 사용해서 로드한 후 사용한다.
typedef struct RectangleType? {
    PointType? topLeft;
    PointType? extent;
} RectangleType?;
; CRect와 비슷하나 extent.x/y 로 width/height을 나타내는게 다르다.

DmOpenRef? DmOpenDatabaseByTypeCreator?(UInt32 type, UInt32 creator, UInt16 mode)
프로그램이 구동될 때 필요한 사전정보를 가져오는 기능으로 사용. (V3.5 이상)

이벤트가 일어났을때, union인 data 구조체에서 해당 이벤트에 알맞은 구조체를 가져온다. (지금 경우는 frmLoadEvent?)

Programming Palm OS in a Nutshell
Why Programming for Palm OS Is Different
화면 크기 ; 통상적으로 160x160 크기가 지원된다.
빠른 반응에 대한 기대 ; 보통 팜 유저는 하루에 15~20번 팜 애플리케이션을 보통 수십초 동안 실행한다.
PC와의 연결성 ; PC-Palm의 연결 수단인 Conduit 프로그램이 존재한다.
입력 방법 ; Graffiti
전원 ; 프로세싱 파워의 제약
메모리 ; 가능하다면, 힙 메모리-속도-코드 사이즈의 순으로 최적화하는것이 좋다.
파일 시스템 ; PalmOS는 record라 불리고, database로 조직되는 메모리 청크에 데이터를 저장할 수 있도록 해준다.
하위 호환성

Palm OS Programming Concepts ; 팜 프로그램은 보통 싱글스레드의 이벤트 드리븐 프로그램이다.
모든 프로그램은 실행될 때 Launch code를 인자로 갖고, 해당 프로그램의 PilotMain?을 호출한다.
PalmOS는 이벤트기반의 운영체제이다. 모든 프로그램은 이벤트 루프를 가지나, 그렇지 않을 수도 있다.
유저 인터페이스는 form들로 구성되며, UI는 미리 정의된 UI 요소, 혹은 사용자 정의 UI 요소를 가질 수 있다.
모든 응용 프로그램은 시스템에서 제공하는 데이터 관리 방법을 사용해야 한다.
PalmOS에서 제공하는 몇몇 관리자들을 사용해서 원하는 기능을 구현하라. 표준 ANSI C 라이브러리는 PalmOS에서 사용할 수는 있으나, 큰 실행 파일을 만들게 된다.

Programming Tools
The CodeWarrior Debugger handles source-level debugging. You can use it with an application running on the Palm OS device, or you can use it in conjunction with one of the other debugging tools below.
The Palm OS Emulator (POSE) tests your application on the desktop computer before downloading it onto the device.
On the Macintosh, you can build a Simulator version of your application to test it. This is a standalone Mac OS application that runs your Palm OS application on a Macintosh computer.
The Palm Debugger is an assembly-level tool. You can also use it to enter commands directly to the Palm device.

Where to Go From Here
Palm OS Companion.pdf
The rest of this book provides details on how to implement common application features using the Palm OS SDK. If you’re new to Palm OS programming, you need to read the next three chapters to learn the principles of Palm OS application and UI design, how to implement the main function, and how to implement the standard event loop. The remaining chapters you can read on an as-needed basis.
Example applications
The actual source code for the applications on the Palm OS device is included as examples on your SDK CD. The code can be a valuable aid when you develop your own program. The software development kit provides a royalty-free license that permits you to use any or all of the source code from the examples in your application.
Palm OS Programming Development Tools Guide
The Palm OS Programming Development Tools Guide provides more details on using the tools to debug programs. (You might also be interested in the “Debugging Strategies”chapter in this book, which describes programmatic debugging solutions.)
Palm OS Programmer’s API Reference
The reference book provides the details on all of the public data structures and API calls.
Conduit Development Kits and documentation
If you need to write a conduit for your application, see the documentation provided with the Conduit Development Kits.


2002년 5월

Visual C++에서의 팜 코드 코딩

GCC 기반으로 Win32 환경에서 팜 프로그래밍을 하면... 솔직히 레퍼런스 보기가 귀찮다. 입력이 제대로 된건지 아닌지도 모르겠고. 그럴 경우 아래 방법을 사용해 보자 :
Visual Assist를 설치한 후, Visual C++을 띄운다. Tools -> Options 메뉴에서 Directories 항목에서 Show directories for: 를 Include files로 선택하고, C:\PALMDEV\SDK-3.5\INCLUDE, C:\PALMDEV\SDK-3.5\INCLUDE\CORE, C:\PALMDEV\SDK-3.5\INCLUDE\CORE\HARDWARE, C:\PALMDEV\SDK-3.5\INCLUDE\CORE\SYSTEM, C:\PALMDEV\SDK-3.5\INCLUDE\CORE\UI 등을 추가한다. (설치한 sdk의 버전에 따라, 혹은 도구의 구성에 따라 경로는 달라질 수 있겠다)
여전히 불편하다면 할 수 없지만, 최소한 함수 이름을 틀리게 입력한 것 같은 사소한 에러는 쉽게 잡을 수 있을 것이다.


Palm에서의 컴파일

m68k-palmos-gcc -palmos3.5 -g

당연한 이야기지만, 상위 버전으로의 호환성은 있어도 하위 버전으로의 호환성은 없다. 가능하면 낮은 버전의 sdk로 컴파일한다.


프로그래밍분류


PythonPowered EditText of this page (last modified 2003-08-01 11:49:42)
FindPage by browsing, searching, or an index
Or try one of these actions: DeletePage, DeleteUploadedFile, LikePages, SpellCheck, UploadFile