Page 1 of 1

C++로 만든 XPCOM에서 XUL 화면 호출

Posted: 2007 05 07 10:11 51
by warmstar
안녕하세요? 이번에 C++로 만든 XPCOM 모듈에서 XUL 화면을 호출하는 방법에
대해 여쭤볼게 있어서 이렇게 글을 올리게 되었습니다.

일단 목적은 XPCOM 모듈에서 사용자가 XUL을 통해 입력한 값을 받아와서
처리하는게 목적입니다.
그런데 XPCOM 모듈에서,

nsCOMPtr<nsIWindowWatcher> wwatch(do_GetService(NS_WINDOWWATCHER_CONTRACTID));
nsCOMPtr<nsIDOMWindow> newWindow;
....
wwatch->OpenWindow (parent, ....)

와 같이 nsIWindowWatcher를 이용하면 Dialog 형태의 화면을 처리하지 못하는 것
같습니다. 위와 같이 할 경우 화면을 띄울때 임의의 인자값을 넣어주어 (제가 구현한
코드에서는 선택할 메뉴를 인자로 넣어줌) 선택할 메뉴를 XPCOM에서 생성하여
전달할 수 있는데 해당 메뉴를 사용자가 선택한 결과값은 가져오기가 힘듭니다.
즉, 다음과 같은 흐름입니다.

1. XPCOM 모듈에서 선택할 인자값 생성
2. XPCOM 모듈에서 XUL 화면 호출
3. XUL 화면에서 사용자가 임의의 값 선택
4. XPCOM 모듈에서 사용자가 선택한 값 확인 (현재 불가)

현재 위와 같은 흐름으로 구현을 하고 싶은데 4번 흐름에서 막혀 있습니다.
혹시 다른 방법을 통해 구현해 보신 분이 계신다면 조언 부탁드리고 싶습니다.

위 방법에 대한 해결책

Posted: 2007 05 22 09:56 13
by warmstar
위 내용과 관련해서 파이어폭스 소스에 훌륭한 예제(?)가 있었습니다.
nsIWindowWatcher에서 사용하고자 하는 함수(OpenWindow)의 내용을 보면
다음과 같습니다.

Code: Select all

  NS_IMETHOD OpenWindow (nsIDOMWindow *aParent,
                               const char *aUrl,
                               const char *aName,
                               const char *aFeatures,
                               nsISupports *aArguments,
                               nsIDOMWindow **_retval) = 0;
위 함수의 인자중 aArguments는 nsISupports 타입으로 대부분의 XPCOM으로 구현되어
있는 모듈을 인자로 넣을 수 있습니다. 따라서 nsIDialogParamBlock 객체를 생성해서
인자로 넘겨주면 XUL 화면과 이를 호출하는 XPCOM 모듈 사이에 메시지를 전달해줄 수 있습니다.
간단하게 nsIDialogParamBlock을 보면,

Code: Select all

class NS_NO_VTABLE nsIDialogParamBlock : public nsISupports {
 public:

  NS_DEFINE_STATIC_IID_ACCESSOR(NS_IDIALOGPARAMBLOCK_IID)

  /** Get or set an interger to pass.
   * Index must be in the range 0..7
   */
  /* PRInt32 GetInt (in PRInt32 inIndex); */
  NS_IMETHOD GetInt(PRInt32 inIndex, PRInt32 *_retval) = 0;

  /* void SetInt (in PRInt32 inIndex, in PRInt32 inInt); */
  NS_IMETHOD SetInt(PRInt32 inIndex, PRInt32 inInt) = 0;

  /** Set the maximum number of strings to pass. Default is 16.
   * Use before setting any string (If you want to change it from the default).
   */
  /* void SetNumberStrings (in PRInt32 inNumStrings); */
  NS_IMETHOD SetNumberStrings(PRInt32 inNumStrings) = 0;

  /** Get or set an string to pass.
    * Index starts at 0
    */
  /* wstring GetString (in PRInt32 inIndex); */
  NS_IMETHOD GetString(PRInt32 inIndex, PRUnichar **_retval) = 0;

  /* void SetString (in PRInt32 inIndex, in wstring inString); */
  NS_IMETHOD SetString(PRInt32 inIndex, const PRUnichar *inString) = 0;

  /**
   * A place where you can store an nsIMutableArray to pass nsISupports 
   */
  /* attribute nsIMutableArray objects; */
  NS_IMETHOD GetObjects(nsIMutableArray * *aObjects) = 0;
  NS_IMETHOD SetObjects(nsIMutableArray * aObjects) = 0;
};

class nsDialogParamBlock: public nsIDialogParamBlock
{
public:
  nsDialogParamBlock();
  virtual ~nsDialogParamBlock();

  NS_DECL_NSIDIALOGPARAMBLOCK
  NS_DECL_ISUPPORTS

private:

  enum {kNumInts = 8, kNumStrings = 16};

  nsresult InBounds(PRInt32 inIndex, PRInt32 inMax) {
    return inIndex >= 0 && inIndex < inMax ? NS_OK : NS_ERROR_ILLEGAL_VALUE;
  }

  PRInt32 mInt[kNumInts];
  PRInt32 mNumStrings;
  nsString* mString;
  nsCOMPtr<nsIMutableArray> mObjects;
};
인데, 위에서 보면 알 수 있듯이 Integer는 8개 String은 16개를 기본으로 사용할 수
있다는 사실을 알 수 있습니다. 실제로 테스트 해본 결과 원하는 결과를 얻을 수 있었습니다.

작업을 진행하면서 느낀 점이지만, 모질라 관련 문서가 많이 존재하지만 그 크기에 비하면 턱없이
부족해보인다는 생각이 들더군요. 이곳에서 그 부족한 부분을 서로 많이 공유했으면 합니다. :lol: