Урок: создаём GUI, часть 1 : Эльфостроение : Форум


 arban:
22.02.09, 22:00
 Урок: создаём графический интерфейс (GUI).

Надеюсь, вы уже скачали и установили svn-клиент TortoiseSVN, компилятор Embedded Workbench 4.0 Evaluation (IAR) и слили в папку свн по адресу svn://svn.boba.su/SE. Если это еще не сделали то вперёд =)

Наша задача - создать меню со списком элементов, притом задать им имя и действие. Начнем...

1. Заходим в папку со слитым репозиторием (далее буду называть это слитой свн), копируем и переименовываем папку HelloWorld в любую другую, например GUI_Example. В папке видим файлы: HelloWorld.eww, main.c, main.ewp и скрытую папку .svn (её можно удалить, но не обязательно, конечно если вы не имеете собственного свн).

2. Открываем файл HelloWorld.eww. Слева ищем слово Debug, жмем на стрелку правее и выбираем Release. Убираем всё лишнее и получаем такой код:

Код: 

#include "..\\\\include\\Lib_Clara.h"
#include "..\\\\include\\Dir.h"

BOOK * HWBook;

int TerminateElf(void * ,BOOK* book)
{
  FreeBook(book);
  return(1);
}

typedef struct
{
  BOOK * book;
}MSG;

int ShowAuthorInfo(void *mess ,BOOK* book)
{
  MSG * msg = (MSG*)mess;
  MessageBox(0x6fFFFFFF,STR("Hello Wordl!\\n\\nExample elf.."),0, 1 ,5000,msg->book);
  return(1);
}

const PAGE_MSG HW_PageEvents[]@ "DYN_PAGE" ={
  ELF_TERMINATE_EVENT , TerminateElf,
  ELF_SHOW_INFO_EVENT  , ShowAuthorInfo,
  0,0
};

PAGE_DESC base_page ={"HW_BasePage",0,HW_PageEvents};


void elf_exit(void)

{
  kill_data(&ELF_BEGIN, (void(*)(void*))mfree_adr());
}

void onCloseHWBook(BOOK * book)
{
  if (book)
  {
    SUBPROC(elf_exit);
  }
}

BOOK * CreateHWBook()
{
  HWBook= new BOOK;
  CreateBook(HWBook,onCloseHWBook,&base_page,"Example",-1,0);
  return(HWBook);
}

int main (void)
{
  CreateHWBook();
  return(0);
}


Этот код также можно сохранить как основу для других эльфов.

Данный код запускает эльф и создаёт для него книгу (далее бук, BOOK). Теперь нам надо создать заголовочный файл (далее модуль), который и будет отвечать за GUI (далее гуи).

3. В папке с нашим проектом создаём файлы gui.c и gui.h. В IAR'е (далее йаре, йар) слева, на панельке щелкаем правой кнопкой мыши и выбираем Add->Add Files..., выбираем файл gui.c. Затем выбираем его (в панельке слева). Видим пустое окно. Вписываем в него следующий код:

Код: 

#include "..\\\\include\\Lib_Clara.h"
#include "..\\\\include\\Dir.h"
#include "gui.h"
#define GUI_NAME L"Example"

void GuiBack(BOOK *bk, void *lt)
{  
  FreeBook((BOOK*)myBook);
}

void GuiOnEnterPressed(BOOK *bk, void *lt)
{     
  int item=ListMenu_GetSelectedItem(myBook->gui);
  if(item==0)
  {
      MessageBox(0x6fFFFFFF,STR("Элемент 1"),0, 1 ,5000,0);
  }
  if(item==1)
  {
      MessageBox(0x6fFFFFFF,STR("Элемент 2"),0, 1 ,5000,0);
  }
}

int GuiOnLBMessage(GUI_MESSAGE * msg)
{
  int item;  
  switch(msg->msg)
  {    
  case 1:
    item=GUIonMessage_GetCreatedItemIndex(msg);    
    if(item==0)    
      SetMenuItemText0(msg,Str2ID(L"Элемент 1",0,SID_ANY_LEN));  
    if(item==1)    
      SetMenuItemText0(msg,Str2ID(L"Элемент 2",0,SID_ANY_LEN)); 
  }
  return(1);
};

void GuiCreateGuiList(void * r0, BOOK * bk)
{  
  myBook->gui=CreateListObject(bk,0);
  GuiObject_SetTitleText(myBook->gui,Str2ID(GUI_NAME,0,SID_ANY_LEN));
  SetNumOfMenuItem(myBook->gui,2);
  OneOfMany_SetonMessage((GUI_ONEOFMANY*)myBook->gui,GuiOnLBMessage);
  SetCursorToItem(myBook->gui,0);
  SetMenuItemStyle(myBook->gui,0);
  GUIObject_Softkey_SetAction(myBook->gui,ACTION_BACK, GuiBack);  
  GUIObject_Softkey_SetAction(myBook->gui,ACTION_LONG_BACK, GuiBack);  
  GUIObject_Softkey_SetAction(myBook->gui,ACTION_SELECT1,GuiOnEnterPressed);     
  ShowWindow(myBook->gui);  
};



А теперь опишу код:
Функция void GuiCreateGuiList(void * r0, BOOK * bk) отвечает за само создание меню. Сначала присвоем структуре myBook->gui (о ней мы поговорим позже) указатель на меню-список. Затем функцией GuiObject_SetTitleText(myBook->gui,Str2ID(GUI_NAME,0,SID_ANY_LEN)) установим заголовок меню, его мы задали в константе GUI_NAME. Потом устанавливаем кол-во пунктов(SetNumOfMenuItem(myBook->gui,2);), названия пунктов (OneOfMany_SetonMessage((GUI_ONEOFMANY*)myBook->gui,GuiOnLBMessage);), установим курсор на первый пункт(SetCursorToItem(myBook->gui,0);), установим стиль меню (SetMenuItemStyle(myBook->gui,0);), посмотреть какие стили существуют можно по сслылке

http://supertrubka.org/wiki/doku.php?id=elflib:functions:setmenuitemstyle.

А теперь зададим действия для софт-клавиш:

Код:

//описание функций GuiBack и GuiOnEnterPressed мы рассмотрим чуть позже
//при коротком и длинном нажатии на клавишу Назад
GUIObject_Softkey_SetAction(myBook->gui,ACTION_BACK, GuiBack);  
GUIObject_Softkey_SetAction(myBook->gui,ACTION_LONG_BACK, GuiBack);  
//при выборе
GUIObject_Softkey_SetAction(myBook->gui,ACTION_SELECT1,GuiOnEnterPressed); 


И, наконец, покажем наше меню (ShowWindow(myBook->gui);).

Функция:

Код:
 
void GuiBack(BOOK *bk, void *lt)
{  
  FreeBook((BOOK*)myBook);
}


отвечает за выход из нашей меню, в ней мы освобождаем созданный нами бук (FreeBook((BOOK*)myBook);). Вместе с буком у нас удалиться и наш гуи.

Функция:
Код: 

void GuiOnEnterPressed(BOOK *bk, void *lt)
{     
  int item=ListMenu_GetSelectedItem(myBook->gui);
  if(item==0)
  {
      MessageBox(0x6fFFFFFF,STR("Элемент 1"),0, 1 ,5000,0);
  }
  if(item==1)
  {
      MessageBox(0x6fFFFFFF,STR("Элемент 2"),0, 1 ,5000,0);
  }
}


отвечает за действие при выборе пункта. Сначала мы функцией ListMenu_GetSelectedItem(myBook->gui) присваиваем переменной item значение текущего выбранного пункта, потом проверяем какой пункт у нас выбран и совершаем действие, в нашем случае выводим сообщение.

Функция:
Код: 

int GuiOnLBMessage(GUI_MESSAGE * msg)
{
  int item;  
  switch(msg->msg)
  {    
  case 1:
    item=GUIonMessage_GetCreatedItemIndex(msg);    
    if(item==0)    
      SetMenuItemText0(msg,Str2ID(L"Элемент 1",0,SID_ANY_LEN));  
    if(item==1)    
      SetMenuItemText0(msg,Str2ID(L"Элемент 2",0,SID_ANY_LEN)); 
  }
  return(1);
};


задаёт пунктам имена, работает почти также как и GuiOnEnterPressed, так что подробно расписывать здесь, думаю не надо.

4. Теперь нам надо запустить это дело. Выбираем в панеле файл main.c и создаём структуру:
Код: 

typedef struct
{
BOOK book;
GUI_LIST*gui;
}MyBOOK;

MyBOOK*myBook;

заместо BOOK * HWBook, где book содержит нашу книгу, а gui указатель на гуи. Его то мы и использовали в нашей менюшке. Теперь необходимо исправить функцию:

Код:

BOOK * CreateHWBook()
{
  HWBook= new BOOK;
  CreateBook(HWBook,onCloseHWBook,&base_page,"Example",-1,0);
  return(HWBook);
}


меняем на:

Код:

MyBOOK * CreateHWBook()
{
  myBook= new MyBOOK;
  CreateBook(myBook,onCloseHWBook,&base_page,"Example",-1,0);
  return(myBook);
}


Почти готово. Далее открываем файл gui.h и вписываем в него:

Код: 

typedef struct
{
BOOK book;
GUI_LIST*gui;
}MyBOOK;
extern MyBOOK*myBook;
extern void GuiCreateGuiList(void * r0, BOOK * bk);



Сохраняем, закрываем. Заходим опять в IAR. Теперь структуру MyBOOK нужно стереть из main.c, так как мы её добавили в gui.h для того чтобы она могла быть использована в других модулях. В функции main перед return(0); пишем GuiCreateGuiList(0, (BOOK*)myBook);.

5. Всё готово! В файле main.c у вас должно быть:

Код: 

#include "..\\\\include\\Lib_Clara.h"
#include "..\\\\include\\Dir.h"
#include "gui.h"

MyBOOK * myBook;

int TerminateElf(void * ,BOOK* book)
{
  FreeBook(book);
  return(1);
}

typedef struct
{
  BOOK * book;
}MSG;

int ShowAuthorInfo(void *mess ,BOOK* book)
{
  MSG * msg = (MSG*)mess;
  MessageBox(0x6fFFFFFF,STR("Hello Wordl!\\n\\nExample elf.."),0, 1 ,5000,msg->book);
  return(1);
}

const PAGE_MSG HW_PageEvents[]@ "DYN_PAGE" ={
  ELF_TERMINATE_EVENT , TerminateElf,
  ELF_SHOW_INFO_EVENT  , ShowAuthorInfo,
  0,0
};

PAGE_DESC base_page ={"HW_BasePage",0,HW_PageEvents};


void elf_exit(void)

{
  kill_data(&ELF_BEGIN, (void(*)(void*))mfree_adr());
}

void onCloseHWBook(BOOK * book)
{
  if (book)
  {
    SUBPROC(elf_exit);
  }
}

MyBOOK * CreateHWBook()
{
  myBook= new MyBOOK;  
  CreateBook(myBook,onCloseHWBook,&base_page,"Example",-1,0);
  return(myBook);
}

int main (void)
{
  CreateHWBook();  
  GuiCreateGuiList(0, (BOOK *)myBook);
  return(0);
}



В gui.c:

Код: 

#include "..\\\\include\\Lib_Clara.h"
#include "..\\\\include\\Dir.h"
#include "gui.h"
#define GUI_NAME L"Example"

void GuiBack(BOOK *bk, void *lt)
{  
  FreeBook((BOOK*)myBook);
}

void GuiOnEnterPressed(BOOK *bk, void *lt)
{     
  int item=ListMenu_GetSelectedItem(myBook->gui);
  if(item==0)
  {
      MessageBox(0x6fFFFFFF,STR("Элемент 1"),0, 1 ,5000,0);
  }
  if(item==1)
  {
      MessageBox(0x6fFFFFFF,STR("Элемент 2"),0, 1 ,5000,0);
  }
}

int GuiOnLBMessage(GUI_MESSAGE * msg)
{
  int item;  
  switch(msg->msg)
  {    
  case 1:
    item=GUIonMessage_GetCreatedItemIndex(msg);    
    if(item==0)    
      SetMenuItemText0(msg,Str2ID(L"Элемент 1",0,SID_ANY_LEN));  
    if(item==1)    
      SetMenuItemText0(msg,Str2ID(L"Элемент 2",0,SID_ANY_LEN)); 
  }
  return(1);
};

void GuiCreateGuiList(void * r0, BOOK * bk)
{  
  myBook->gui=CreateListObject(bk,0);
  GuiObject_SetTitleText(myBook->gui,Str2ID(GUI_NAME,0,SID_ANY_LEN));
  SetNumOfMenuItem(myBook->gui,2);
  OneOfMany_SetonMessage((GUI_ONEOFMANY*)myBook->gui,GuiOnLBMessage);
  SetCursorToItem(myBook->gui,0);
  SetMenuItemStyle(myBook->gui,0);
  GUIObject_Softkey_SetAction(myBook->gui,ACTION_BACK, GuiBack);  
  GUIObject_Softkey_SetAction(myBook->gui,ACTION_LONG_BACK, GuiBack);  
  GUIObject_Softkey_SetAction(myBook->gui,ACTION_SELECT1,GuiOnEnterPressed);     
  ShowWindow(myBook->gui);  
};



В gui.h:

Код: 

typedef struct
{
BOOK book;
GUI_LIST*gui;
}MyBOOK;
extern MyBOOK * myBook;
extern void GuiCreateGuiList(void * r0, BOOK * bk);



Всё, теперь можно скомпилировать наш эльф. Просто жмём F7, если всё сделали правильно, то внизу должен появиться лог:

Код:

Building configuration: main - Release 
Updating build tree... 
gui.c 
main.c 
Linking 


Идём в папку Release/Exe/ и забираем наш эльф main.elf. Вот и всё! Мы научились создавать простейшую меню со списком пунктов.

(c)arban

 MODDER-GT:
24.04.10, 13:16
 ..Убираем всё лишнее и получаем такой код... где именно убираем?

 arban:
24.04.10, 14:28
 MODDER-GT, в файле main.c

Да и вообще, урок устарел и ошибки, возможно, есть

 cachok9999:
25.04.10, 18:18
 Defined,
can you make a GUI to put an Image background?
Regards

 arban:
19.07.10, 11:29
 Жестокий код. А инициализацию myBook кто делать будет? Посмотри исходники на свн, как сказал JokerXT, как там всё устроено и т.д.

 Pavlus:
19.07.10, 12:10
 Вот, кажется так правильно:
Код: 
#include "..\\include\Lib_Clara.h"
#include "..\\include\Dir.h"
#include "gui.h"

MyBOOK * myBook;
u16 timer;
char *BookName="MyBook";

void elf_exit(void)

{
  kill_data(&ELF_BEGIN, (void(*)(void*))mfree_adr());
}
int TerminateElf(void * ,BOOK* book)
{
  FreeBook(book);
  return(1);
}

typedef struct
{
  BOOK * book;
}MSG;

int ShowAuthorInfo(void *mess ,BOOK* book)
{
  MSG * msg = (MSG*)mess;
  MessageBox(EMPTY_SID,STR("Hello Wordl!\n\nExample elf.."), NOIMAGE, 1, 5000,msg->book);
  return(1);
}

const PAGE_MSG MY_PageEvents[]@ "DYN_PAGE" ={
  ELF_TERMINATE_EVENT , TerminateElf,
  ELF_SHOW_INFO_EVENT  , ShowAuthorInfo,
  0,0
};

PAGE_DESC base_page ={"MY_BasePage",0,MY_PageEvents};

void onCloseMYBook(BOOK * book)
{
  if (book)
  {
    SUBPROC(elf_exit);
  }
}
//------------------------------------------------------------------------------
int isMyElfBook(BOOK * book){
//return 0==strcmp(book->xbook->name,BookName);
  if(!strcmp(book->xbook->name,BookName)) return(1);
return(0);
}
int checkMyBookExist(void){
  if(FindBook(isMyElfBook)){
    return(1);
  }
  return(0);
}
MyBOOK * CreateMYBook()
{
  myBook= new MyBOOK;
  CreateBook(&(myBook->book),onCloseMYBook,&base_page,BookName,-1,0);
  return(myBook);
}
//------------------------------------------------------------------------------
void reportElfIsStarted(BOOK * book){
    const int bufsize=strlen(BookName)+strlen(" is running");
    char * strMsg=new char[bufsize+1];
    strcpy(strMsg,BookName);
    strcat(strMsg," is running");
    MessageBox(0x6FFFFFFF,Str2ID(strMsg,6,SID_ANY_LEN),NOIMAGE,1,5000,0);
    if(strMsg)delete(strMsg);
}
int main (void)
{
  if(FindBook(isMyElfBook)){ 
    reportElfIsStarted;
    TerminateElf;
  }
  else{
    CreateMYBook();
    GuiCreateGuiList(0, &(myBook->book));
  }
  return(0);
}



 lexa4311:
01.08.10, 22:32
 mugen, прихлопнули тебя, да, месть арбана жестока, согласен конечно
p.s. у меня тоже w810 ;-)

URL этой темы:
https://mobilefree.justdanpo.ru/newbb_plus/viewtopic.php?topic_id=3730

© 2005-2018 supertrubka.org