void OUGUICallBackObject::RunCallBack(string name, OUGUIObject* pSender, OUGUIEvent* pEvent)
{
    OUGUI_CBWRAPPER* pWrapper = GetCallBack(name);
    if(NULL == pWrapper) return;

    (pWrapper->pPar->*(pWrapper->pFunc))(pSender, pEvent);
}
Exemple #2
0
static DataField *
LoadDataField(const XMLNode &node, const CallBackTableEntry *LookUpTable)
{
  TCHAR data_type[32];
  TCHAR display_format[32];
  TCHAR edit_format[32];
  double step;
  bool fine;

  _tcscpy(data_type,
          StringToStringDflt(node.getAttribute(_T("DataType")), _T("")));
  _tcscpy(display_format,
          StringToStringDflt(node. getAttribute(_T("DisplayFormat")), _T("")));
  _tcscpy(edit_format,
          StringToStringDflt(node.getAttribute(_T("EditFormat")), _T("")));

  fixed min = fixed(StringToFloatDflt(node.getAttribute(_T("Min")), INT_MIN));
  fixed max = fixed(StringToFloatDflt(node.getAttribute(_T("Max")), INT_MAX));
  step = StringToFloatDflt(node.getAttribute(_T("Step")), 1);
  fine = StringToIntDflt(node.getAttribute(_T("Fine")), false);

  DataField::DataAccessCallback callback = (DataField::DataAccessCallback)
    GetCallBack(LookUpTable, node, _T("OnDataAccess"));

  if (_tcsicmp(data_type, _T("enum")) == 0)
    return new DataFieldEnum(callback);

  if (_tcsicmp(data_type, _T("filereader")) == 0) {
    DataFieldFileReader *df = new DataFieldFileReader(callback);

    if (StringToIntDflt(node.getAttribute(_T("Nullable")), true))
      df->AddNull();

    return df;
  }

  if (_tcsicmp(data_type, _T("boolean")) == 0)
    return new DataFieldBoolean(false, _("On"), _("Off"), callback);

  if (_tcsicmp(data_type, _T("double")) == 0)
    return new DataFieldFloat(edit_format, display_format, min, max,
                              fixed_zero, fixed(step), fine, callback);

  if (_tcsicmp(data_type, _T("time")) == 0) {
    DataFieldTime *df = new DataFieldTime((int)min, (int)max, 0,
                                          (unsigned)step, callback);
    unsigned max_token = StringToIntDflt(node.getAttribute(_T("MaxTokens")), 2);
    df->SetMaxTokenNumber(max_token);
    return df;
  }

  if (_tcsicmp(data_type, _T("integer")) == 0)
    return new DataFieldInteger(edit_format, display_format, (int)min, (int)max,
                                0, (int)step, callback);

  if (_tcsicmp(data_type, _T("string")) == 0)
    return new DataFieldString(_T(""), callback);

  return NULL;
}
Exemple #3
0
/**
 * Creates a control from the given XMLNode as a child of the given
 * parent.
 *
 * @param form the WndForm object
 * @param LookUpTable The parent CallBackTable
 * @param node The XMLNode that represents the control
 * @param eDialogStyle The parent's dialog style
 */
static Window *
LoadChild(WndForm &form, ContainerWindow &parent, Color background_color,
          CallBackTableEntry *LookUpTable,
          XMLNode node, const DialogStyle eDialogStyle,
          int bottom_most=0)
{
  Window *window = NULL;

  // Determine name, coordinates, width, height
  // and caption of the control
  const TCHAR* Name = GetName(node);
  const TCHAR* Caption = GetCaption(node);
  RECT rc = parent.get_client_rect();
  ControlPosition pos = GetPosition(node, rc, bottom_most);
  if (!pos.no_scaling)
    pos.x = ScaleWidth(pos.x, eDialogStyle);

  ControlSize size = GetSize(node, rc, pos);
  if (!size.no_scaling)
    size.cx = ScaleWidth(size.cx, eDialogStyle);

  WindowStyle style;

  if (!StringToIntDflt(node.getAttribute(_T("Visible")), 1))
    style.hide();

  if (StringToIntDflt(node.getAttribute(_T("Border")), 0))
    style.border();

  bool advanced = _tcschr(Caption, _T('*')) != NULL;

  // PropertyControl (WndProperty)
  if (_tcscmp(node.getName(), _T("Edit")) == 0) {
    WndProperty *W;
    int CaptionWidth;
    bool ReadOnly;
    bool MultiLine;

    // Determine the width of the caption field
    CaptionWidth = StringToIntDflt(node.getAttribute(_T("CaptionWidth")), 0);

    if (Layout::ScaleSupported())
      CaptionWidth = Layout::Scale(CaptionWidth);

    CaptionWidth = ScaleWidth(CaptionWidth, eDialogStyle);

    // Determine whether the control is multiline or readonly
    MultiLine = StringToIntDflt(node.getAttribute(_T("MultiLine")), 0);
    ReadOnly = StringToIntDflt(node.getAttribute(_T("ReadOnly")), 0);

    // Load the event callback properties
    WndProperty::DataChangeCallback_t DataNotifyCallback =
      (WndProperty::DataChangeCallback_t)
      GetCallBack(LookUpTable, node, _T("OnDataNotify"));

    WindowControl::OnHelpCallback_t OnHelpCallback =
      (WindowControl::OnHelpCallback_t)
      GetCallBack(LookUpTable, node, _T("OnHelp"));

    // Create the Property Control
    style.control_parent();

    EditWindowStyle edit_style;
    if (ReadOnly)
      edit_style.read_only();
    else
      edit_style.tab_stop();

    if (is_embedded() || Layout::scale_1024 < 2048)
      /* sunken edge doesn't fit well on the tiny screen of an
         embedded device */
      edit_style.border();
    else
      edit_style.sunken_edge();

    if (MultiLine) {
      edit_style.multiline();
      edit_style.vscroll();
    }

    window = W = new WndProperty(parent, Caption,
                                 pos.x, pos.y, size.cx, size.cy,
                                 CaptionWidth, background_color,
                                 style, edit_style,
                                 DataNotifyCallback);

    // Set the fore- and background color
    LoadColors(*W, node);

    // Set the help function event callback
    W->SetOnHelpCallback(OnHelpCallback);

    // Load the help text
    W->SetHelpText(StringToStringDflt(node.getAttribute(_T("Help")), _T("")));

    // If the control has (at least) one DataField child control
    if (node.nChildNode(_T("DataField")) > 0){
      // -> Load the first DataField control
      DataField *data_field =
        LoadDataField(node.getChildNode(_T("DataField"), 0),
                      LookUpTable, eDialogStyle);

      if (data_field != NULL)
        // Tell the Property control about the DataField control
        W->SetDataField(data_field);
    }

  // ButtonControl (WndButton)
  } else if (_tcscmp(node.getName(), _T("Button")) == 0) {
    // Determine ClickCallback function
    WndButton::ClickNotifyCallback_t ClickCallback =
      (WndButton::ClickNotifyCallback_t)
      GetCallBack(LookUpTable, node, _T("OnClick"));

    // Create the ButtonControl

    ButtonWindowStyle bstyle(style);
    bstyle.tab_stop();
    bstyle.multiline();

    window = new WndButton(parent, Caption,
                           pos.x, pos.y, size.cx, size.cy,
                           bstyle, ClickCallback);

  } else if (_tcscmp(node.getName(), _T("CheckBox")) == 0) {
    // Determine ClickCallback function
    CheckBoxControl::ClickNotifyCallback_t ClickCallback =
      (CheckBoxControl::ClickNotifyCallback_t)
      GetCallBack(LookUpTable, node, _T("OnClick"));

    // Create the CheckBoxControl

    style.tab_stop();

    window = new CheckBoxControl(parent, Caption,
                                 pos.x, pos.y, size.cx, size.cy,
                                 style,
                                 ClickCallback);

  // SymbolButtonControl (WndSymbolButton) not used yet
  } else if (_tcscmp(node.getName(), _T("SymbolButton")) == 0) {
    // Determine ClickCallback function
    WndButton::ClickNotifyCallback_t ClickCallback =
      (WndButton::ClickNotifyCallback_t)
      GetCallBack(LookUpTable, node, _T("OnClick"));

    // Create the SymbolButtonControl

    style.tab_stop();

    window = new WndSymbolButton(parent, Caption,
                                 pos.x, pos.y, size.cx, size.cy,
                                 style, background_color,
                                 ClickCallback);

  // PanelControl (WndPanel)
  } else if (_tcscmp(node.getName(), _T("Panel")) == 0) {
    // Create the PanelControl

    style.control_parent();

    PanelControl *frame = new PanelControl(parent,
                                           pos.x, pos.y, size.cx, size.cy,
                                           background_color, style);

    window = frame;

    // Load children controls from the XMLNode
    LoadChildrenFromXML(form, *frame, background_color,
                        LookUpTable, &node, eDialogStyle);

  // KeyboardControl
  } else if (_tcscmp(node.getName(), _T("Keyboard")) == 0) {
    KeyboardControl::OnCharacterCallback_t CharacterCallback =
      (KeyboardControl::OnCharacterCallback_t)
      GetCallBack(LookUpTable, node, _T("OnCharacter"));

    // Create the KeyboardControl
    KeyboardControl *kb =
      new KeyboardControl(parent,
                          pos.x, pos.y, size.cx, size.cy, background_color,
                          CharacterCallback, style);

    window = kb;
  // DrawControl (WndOwnerDrawFrame)
  } else if (_tcscmp(node.getName(), _T("Canvas")) == 0) {
    // Determine DrawCallback function
    WndOwnerDrawFrame::OnPaintCallback_t PaintCallback =
      (WndOwnerDrawFrame::OnPaintCallback_t)
      GetCallBack(LookUpTable, node, _T("OnPaint"));

    // Create the DrawControl
    WndOwnerDrawFrame* canvas =
      new WndOwnerDrawFrame(parent,
                            pos.x, pos.y, size.cx, size.cy,
                              style, PaintCallback);

    window = canvas;

  // FrameControl (WndFrame)
  } else if (_tcscmp(node.getName(), _T("Label")) == 0){
    // Create the FrameControl
    WndFrame* frame = new WndFrame(parent,
                                   pos.x, pos.y, size.cx, size.cy,
                                   background_color, style);

    // Set the caption
    frame->SetCaption(Caption);

    window = frame;

  // ListBoxControl (WndListFrame)
  } else if (_tcscmp(node.getName(), _T("List")) == 0){
    // Determine ItemHeight of the list items
    unsigned item_height =
      Layout::Scale(StringToIntDflt(node.getAttribute(_T("ItemHeight")), 18));

    // Create the ListBoxControl

    style.tab_stop();

    if (is_embedded() || Layout::scale_1024 < 2048)
      /* sunken edge doesn't fit well on the tiny screen of an
         embedded device */
      style.border();
    else
      style.sunken_edge();

    window = new WndListFrame(parent,
                              pos.x, pos.y, size.cx, size.cy,
                              style,
                              item_height);

  // TabControl (Tabbed)
  } else if (_tcscmp(node.getName(), _T("Tabbed")) == 0) {
    // Create the TabControl

    style.control_parent();

    TabbedControl *tabbed = new TabbedControl(parent,
                                              pos.x, pos.y, size.cx, size.cy,
                                              style);

    window = tabbed;

    const unsigned n = node.nChildNode();
    for (unsigned i = 0; i < n; ++i) {
      // Load each child control from the child nodes
      Window *child = LoadChild(form, *tabbed, background_color,
                                LookUpTable,
                                node.getChildNode(i), eDialogStyle);
      if (child != NULL)
        tabbed->AddClient(child);
        continue;
    }
  } else if (_tcscmp(node.getName(), _T("Custom")) == 0) {
    // Create a custom Window object with a callback
    CreateWindowCallback_t create =
        (CreateWindowCallback_t)GetCallBack(LookUpTable, node, _T("OnCreate"));
    if (create == NULL)
      return NULL;

    window = create(parent,
                    pos.x, pos.y, size.cx, size.cy, style);
  }

  if (window != NULL) {
    if (!string_is_empty(Name))
      form.AddNamed(Name, window);

    if (advanced)
      form.AddAdvanced(window);

    form.AddDestruct(window);
  }

  return window;
}
Exemple #4
0
/*
	ExecLine function
*/
inline int ExecLine(struct ST_SUIM *pS, const char *pchLine)
{
	if(pS->inFlgError== 1) return (ERR_NONE);

	if(pchLine[0]== 'i' && pchLine[1]== ':') {
		//if
		Calc(pS);
		if(pS->inErrCode!= SUCCESS) return (pS->inErrCode);

		if(pS->doCalcWork== 1.0) {
			return (pS->inLineNo + 1);
		}
		else {
			int inLineNo = pS->pinListJumpNo[pS->inLineNo];
			return (inLineNo);
		}
	}
	else {
		if(pchLine[0]== 'g' && pchLine[1]== ':') {
			//goto
			int inLineNo = pS->pinListJumpNo[pS->inLineNo];
			return (inLineNo);
		}
		else {
			if(pchLine[0]== 'c' && pchLine[1]== ':') {
				//call function
				if(pS->pchInArgs!= NULL) {
					free(pS->pchInArgs);
					pS->pchInArgs = NULL;
				}

				char pchFuncName[MAX_WORD] = "";

				CallBack pclCallBack = NULL;
				char *pchIndex = strchr(&pchLine[2], ' ');
				if(pchIndex== NULL) {
					strcpy(pchFuncName, &pchLine[2]);

					pclCallBack = GetCallBack(pS, &pchLine[2]);
				}
				else {
					char *pchInArgs = pchIndex + 1;

					int inSize = pchIndex - &pchLine[2];
					memset(pchFuncName, 0x00, MAX_WORD);
					strncpy(pchFuncName, &pchLine[2], inSize);

					pclCallBack = GetCallBack(pS, pchFuncName);
					if(pclCallBack!= NULL) {
						int inLength = strlen(pchInArgs);
						pS->pchInArgs = malloc(inLength + 1);
						strcpy(pS->pchInArgs, pchInArgs);
					}
				}

				if(pclCallBack!= NULL) {
					//exe side function
					int inErrCode = (*pclCallBack)((int *)pS);
					if(inErrCode!= SUCCESS) {
						SetError2(pS, inErrCode, "function call error.");
						return (inErrCode);
					}
				}
				else {
					//suim function
					if(pS->inStackBackNo>= MAX_STACK_FUNCTION) {
						SetError2(pS, ERR_OVERFLOW, "function stack overflow.");
						return (ERR_OVERFLOW);
					}

					pS->pinStackBackNo[pS->inStackBackNo] = pS->inLineNo;
					pS->inStackBackNo++;

					int inLineNo = GetFunctionDefine(pS, pchFuncName);
					if(inLineNo== 0) {
						SetError2(pS, ERR_FUNC_NAME, "can't find function name.");
						return (ERR_FUNC_NAME);
					}

					pS->inLineNo = inLineNo;
				}

				pS->inNoOut = 0;

				return (pS->inLineNo + 1);
			}
			else {
				if(pchLine[0]== 'o' && pchLine[1]== ':') {
					//setup out arg
					Calc(pS);
					if(pS->inErrCode!= SUCCESS) return (pS->inErrCode);

					if(pS->pchCalcWork== NULL) {
						int inErrCode = SetValueDouble(pS->ppstListOut, pS->inNoOut, pS->doCalcWork);
						if(inErrCode!= SUCCESS) return (inErrCode);
					}
					else {
						int inErrCode = SetValueString(pS->ppstListOut, pS->inNoOut, pS->pchCalcWork);
						if(inErrCode!= SUCCESS) return (inErrCode);
					}
					pS->inNoOut++;

					return (pS->inLineNo + 1);
				}
				else {
					if(pchLine[0]== '-' && pchLine[1]== '-') {
						//Separator
						return (ORDER_SEPARATOR);
					}
					else {
						if(pchLine[0]== 'r' && pchLine[1]== ':') {
							//return
							pS->inNoOut = 0;

							return (ORDER_RETURN);
						}
						else {
							if(pchLine[0]== 'e' && pchLine[1]== ':') {
								//function end
								if(pS->inStackBackNo>= 1) {
									pS->inLineNo = pS->pinStackBackNo[pS->inStackBackNo - 1];
									pS->pinStackBackNo[pS->inStackBackNo - 1] = 0;
									pS->inStackBackNo--;

									return (pS->inLineNo + 1);
								}

								return (ORDER_END);
							}
						}
					}
				}
			}
		}
	}

	//calculation
	int inNo = CngKey2No(&pchLine[0]);
	if(inNo< 0) return (ERR_OVERFLOW);
	if(inNo>= pS->inCountVariable) return (ERR_OVERFLOW);

	Calc(pS);
	if(pS->inErrCode!= SUCCESS) return (pS->inErrCode);

	int inErrCode = SUCCESS;
	if(pS->pchCalcWork== NULL) {
		inErrCode = SetValueDouble(pS->ppstListVariable, inNo, pS->doCalcWork);
	}
	else {
		inErrCode = SetValueString(pS->ppstListVariable, inNo, pS->pchCalcWork);

		free(pS->pchCalcWork);
		pS->pchCalcWork = NULL;
	}
	if(inErrCode!= SUCCESS) return (inErrCode);

	return (pS->inLineNo + 1);
}
Exemple #5
0
/**
 * Creates a control from the given XMLNode as a child of the given
 * parent.
 *
 * @param form the SubForm object
 * @param LookUpTable The parent CallBackTable
 * @param node The XMLNode that represents the control
 */
static Window *
LoadChild(SubForm &form, ContainerWindow &parent,
          const CallBackTableEntry *lookup_table, XMLNode node,
          int bottom_most,
          WindowStyle style)
{
  Window *window = NULL;

  // Determine name, coordinates, width, height
  // and caption of the control
  const TCHAR* name = GetName(node);
  const TCHAR* caption = GetCaption(node);
  PixelRect rc = parent.get_client_rect();
  ControlPosition pos = GetPosition(node, rc, bottom_most);
  if (!pos.no_scaling)
    pos.x = ScaleWidth(pos.x);

  ControlSize size = GetSize(node, rc, pos);
  if (!size.no_scaling)
    size.cx = ScaleWidth(size.cx);

  if (!StringToIntDflt(node.getAttribute(_T("Visible")), 1))
    style.Hide();

  if (StringToIntDflt(node.getAttribute(_T("Border")), 0))
    style.Border();

  rc.left = pos.x;
  rc.top = pos.y;
  rc.right = rc.left + size.cx;
  rc.bottom = rc.top + size.cy;

  bool expert = (StringToIntDflt(node.getAttribute(_T("Expert")), 0) == 1);

  // PropertyControl (WndProperty)
  if (StringIsEqual(node.getName(), _T("Edit"))) {
    // Determine the width of the caption field
    int caption_width = StringToIntDflt(node.getAttribute(_T("CaptionWidth")), 0);

    if (Layout::ScaleSupported())
      caption_width = Layout::Scale(caption_width);

    caption_width = ScaleWidth(caption_width);

    // Determine whether the control is multiline or readonly
    bool multi_line = StringToIntDflt(node.getAttribute(_T("MultiLine")), 0);
    bool read_only = StringToIntDflt(node.getAttribute(_T("ReadOnly")), 0);

    // Load the event callback properties
    WndProperty::DataChangeCallback_t data_notify_callback =
      (WndProperty::DataChangeCallback_t)
      GetCallBack(lookup_table, node, _T("OnDataNotify"));

    WindowControl::HelpCallback help_callback =
      (WindowControl::HelpCallback)
      GetCallBack(lookup_table, node, _T("OnHelp"));

    // Create the Property Control
    style.ControlParent();

    EditWindowStyle edit_style;
    edit_style.vertical_center();
    if (read_only)
      edit_style.read_only();
    else
      edit_style.TabStop();

    if (IsEmbedded() || Layout::scale_1024 < 2048)
      /* sunken edge doesn't fit well on the tiny screen of an
         embedded device */
      edit_style.Border();
    else
      edit_style.SunkenEdge();

    if (multi_line) {
      edit_style.multiline();
      edit_style.VerticalScroll();
    }

    WndProperty *property;
    window = property = new WndProperty(parent, *xml_dialog_look, caption, rc,
                                        caption_width, style, edit_style,
                                        data_notify_callback);

    // Set the help function event callback
    property->SetOnHelpCallback(help_callback);

    // Load the help text
    property->SetHelpText(StringToStringDflt(node.getAttribute(_T("Help")),
                                             NULL));

    // If the control has (at least) one DataField child control
    const XMLNode *data_field_node = node.getChildNode(_T("DataField"));
    if (data_field_node != NULL) {
      // -> Load the first DataField control
      DataField *data_field =
        LoadDataField(*data_field_node, lookup_table);

      if (data_field != NULL)
        // Tell the Property control about the DataField control
        property->SetDataField(data_field);
    }

  } else if (StringIsEqual(node.getName(), _T("TextEdit"))) {
    // Determine whether the control is multiline or readonly
    bool multi_line = StringToIntDflt(node.getAttribute(_T("MultiLine")), 0);
    bool read_only = StringToIntDflt(node.getAttribute(_T("ReadOnly")), 0);

    EditWindowStyle edit_style(style);
    if (read_only)
      edit_style.read_only();
    else
      edit_style.TabStop();

    if (IsEmbedded() || Layout::scale_1024 < 2048)
      /* sunken edge doesn't fit well on the tiny screen of an
         embedded device */
      edit_style.Border();
    else
      edit_style.SunkenEdge();

    if (multi_line) {
      edit_style.multiline();
      edit_style.VerticalScroll();
    }

    EditWindow *edit;
    window = edit = new EditWindow();
    edit->set(parent, pos.x, pos.y, size.cx, size.cy, edit_style);
    edit->InstallWndProc();
    edit->set_font(*xml_dialog_look->text_font);

  // ButtonControl (WndButton)
  } else if (StringIsEqual(node.getName(), _T("Button"))) {
    // Determine ClickCallback function
    WndButton::ClickNotifyCallback click_callback =
      (WndButton::ClickNotifyCallback)
      GetCallBack(lookup_table, node, _T("OnClick"));

    // Create the ButtonControl

    ButtonWindowStyle button_style(style);
    button_style.TabStop();
    button_style.multiline();

    window = new WndButton(parent, *xml_dialog_look, caption,
                           rc,
                           button_style, click_callback);

  } else if (StringIsEqual(node.getName(), _T("CheckBox"))) {
    // Determine click_callback function
    CheckBoxControl::ClickNotifyCallback click_callback =
      (CheckBoxControl::ClickNotifyCallback)
      GetCallBack(lookup_table, node, _T("OnClick"));

    // Create the CheckBoxControl

    style.TabStop();

    window = new CheckBoxControl(parent, *xml_dialog_look, caption,
                                 rc,
                                 style, click_callback);

  // SymbolButtonControl (WndSymbolButton) not used yet
  } else if (StringIsEqual(node.getName(), _T("SymbolButton"))) {
    // Determine ClickCallback function
    WndButton::ClickNotifyCallback click_callback =
      (WndButton::ClickNotifyCallback)
      GetCallBack(lookup_table, node, _T("OnClick"));

    // Create the SymbolButtonControl

    style.TabStop();

    window = new WndSymbolButton(parent, *xml_dialog_look, caption,
                                 rc,
                                 style, click_callback);

  // PanelControl (WndPanel)
  } else if (StringIsEqual(node.getName(), _T("Panel"))) {
    // Create the PanelControl

    style.ControlParent();

    PanelControl *frame = new PanelControl(parent, *xml_dialog_look,
                                           rc,
                                           style);

    window = frame;

    // Load children controls from the XMLNode
    LoadChildrenFromXML(form, *frame,
                        lookup_table, &node);

  // KeyboardControl
  } else if (StringIsEqual(node.getName(), _T("Keyboard"))) {
    KeyboardControl::OnCharacterCallback_t character_callback =
      (KeyboardControl::OnCharacterCallback_t)
      GetCallBack(lookup_table, node, _T("OnCharacter"));

    // Create the KeyboardControl
    KeyboardControl *kb =
      new KeyboardControl(parent, *xml_dialog_look,
                          pos.x, pos.y, size.cx, size.cy,
                          character_callback, style);

    window = kb;
  // DrawControl (WndOwnerDrawFrame)
  } else if (StringIsEqual(node.getName(), _T("Canvas"))) {
    // Determine DrawCallback function
    WndOwnerDrawFrame::OnPaintCallback_t paint_callback =
      (WndOwnerDrawFrame::OnPaintCallback_t)
      GetCallBack(lookup_table, node, _T("OnPaint"));

    // Create the DrawControl
    WndOwnerDrawFrame* canvas =
      new WndOwnerDrawFrame(parent, pos.x, pos.y, size.cx, size.cy,
                            style, paint_callback);

    window = canvas;

  // FrameControl (WndFrame)
  } else if (StringIsEqual(node.getName(), _T("Label"))){
    // Create the FrameControl
    WndFrame* frame = new WndFrame(parent, *xml_dialog_look,
                                   pos.x, pos.y, size.cx, size.cy,
                                   style);

    // Set the caption
    frame->SetCaption(caption);
    // Set caption color
    Color color;
    if (StringToColor(node.getAttribute(_T("CaptionColor")), color))
      frame->SetCaptionColor(color);

    window = frame;

  // ListBoxControl (WndListFrame)
  } else if (StringIsEqual(node.getName(), _T("List"))){
    // Determine ItemHeight of the list items
    UPixelScalar item_height =
      Layout::Scale(StringToIntDflt(node.getAttribute(_T("ItemHeight")), 18));

    // Create the ListBoxControl

    style.TabStop();

    if (IsEmbedded() || Layout::scale_1024 < 2048)
      /* sunken edge doesn't fit well on the tiny screen of an
         embedded device */
      style.Border();
    else
      style.SunkenEdge();

    window = new WndListFrame(parent, *xml_dialog_look,
                              pos.x, pos.y, size.cx, size.cy,
                              style,
                              item_height);

  // TabControl (Tabbed)
  } else if (StringIsEqual(node.getName(), _T("Tabbed"))) {
    // Create the TabControl

    style.ControlParent();

    TabbedControl *tabbed = new TabbedControl(parent,
                                              pos.x, pos.y, size.cx, size.cy,
                                              style);

    window = tabbed;

    for (auto i = node.begin(), end = node.end(); i != end; ++i) {
      // Load each child control from the child nodes
      Window *child = LoadChild(form, *tabbed,
                                lookup_table,
                                *i);
      if (child != NULL)
        tabbed->AddClient(child);
    }
  // TabBarControl (TabBar)
  } else if (StringIsEqual(node.getName(), _T("TabBar"))) {
    // Create the TabBarControl

    bool flip_orientation = false;
    if ( (Layout::landscape && StringToIntDflt(node.getAttribute(_T("Horizontal")), 0)) ||
         (!Layout::landscape && StringToIntDflt(node.getAttribute(_T("Vertical")), 0) ) )
      flip_orientation = true;

    style.ControlParent();
    TabBarControl *tabbar = new TabBarControl(parent, *xml_dialog_look,
                                              pos.x, pos.y, size.cx, size.cy,
                                              style, flip_orientation);
    window = tabbar;

    // TabMenuControl (TabMenu)
  } else if (StringIsEqual(node.getName(), _T("TabMenu"))) {
    // Create the TabMenuControl

    style.ControlParent();
    TabMenuControl *tabmenu = new TabMenuControl(parent,
                                                 /* XXX this cast is
                                                    an ugly hack!
                                                    Please rewrite: */
                                                 (WndForm &)form,
                                                 *xml_dialog_look, caption,
                                                 pos.x, pos.y, size.cx, size.cy,
                                                 style);
    window = tabmenu;

  } else if (StringIsEqual(node.getName(), _T("Custom"))) {
    // Create a custom Window object with a callback
    CreateWindowCallback_t create_callback =
        (CreateWindowCallback_t)GetCallBack(lookup_table, node, _T("OnCreate"));
    if (create_callback == NULL)
      return NULL;

    window = create_callback(parent, pos.x, pos.y, size.cx, size.cy, style);
  } else if (StringIsEqual(node.getName(), _T("Widget"))) {
    style.ControlParent();
    DockWindow *dock = new DockWindow();
    dock->set(parent, rc, style);
    window = dock;
  }

  if (window != NULL) {
    if (!StringIsEmpty(name))
      form.AddNamed(name, window);

    if (expert)
      form.AddExpert(window);

    form.AddDestruct(window);
  }

  return window;
}