Menu

Example: Create tabpages from resources

Stephan
2006-07-25
2013-04-08
  • Stephan

    Stephan - 2006-07-25

    Hi!

    I modified WidgetTabSheet, now it's possible to add every WidgetDialog as a tabpage. I hope my changes will be added to CVS aggain. For example I created three dialogs from resources:

    /*
      In this way you could use an array of WidgetTabPage, too. I decide to create one object for each tabpage,
      because this let you the ability to design each page with different controls.
    */
    #include "SmartWin.h"
    #include "resource.h"

    using namespace SmartWin;

    class WidgetTabPage
        : public WidgetFactory<WidgetDialog, WidgetTabPage, DialogWidget >
    {
    public:
        WidgetTabPage(Widget * parent, UINT dlgresid)
            : Widget(parent)
        {
            createDialog( dlgresid );
            addRemoveStyle( WS_POPUP, false ); // Means take away WS_POPUP
            addRemoveStyle( WS_CHILD, true ); // and add WS_CHILD
            addRemoveStyle( WS_EX_CONTROLPARENT, true);
        }

    };

    class WidgetTest1
        : public WidgetFactory< WidgetWindow, WidgetTest1 >
    {
        WidgetTabSheetPtr sheet;
        WidgetTabPage* page1;
        WidgetTabPage* page2;
        WidgetTabPage* page3;

    public:
        void tabSelectionChanged( WidgetTabSheetPtr sheet )
        {
            bool v[3] = { false, false, false };
            v[sheet->getSelectedIndex()] = true;
            page1->setVisible(v[0]);
            page2->setVisible(v[1]);
            page3->setVisible(v[2]);
        }

        bool closing()
        {
            page1->close();
            page2->close();
            page3->close();
            return true;
        }

        void initAndCreate()
        {
            // Creating main Widget
            WidgetWindow::Seed windowCS;

            windowCS.rect = SmartWin::Rectangle( 100, 100, 730, 570 );
            windowCS.Background = CreateSolidBrush( RGB( 0, 0, 125 ) );
            windowCS.Caption = _T("WidgetTabSheet - example application for tab controls!");
            createWindow( windowCS );
            onClosing( &WidgetTest1::closing );

            // Creating tab sheet
            sheet = createTabSheet();
            sheet->setBounds( 10, 10, 700, 500 );
            sheet->onSelectionChanged( &WidgetTest1::tabSelectionChanged );
            sheet->setTabsAtBottom();
            sheet->setTabsAtBottom( false );
            sheet->setButtonStyle();
            sheet->setButtonStyle( false );
            sheet->setHotTrack();
           
            //receive display area
            struct SmartWin::Rectangle displayarea = sheet->getDisplayRect();

            sheet->addPage( "Page 1", 0 );
            page1 = new WidgetTabPage(this, IDD_DIALOG1);
            page1->setBounds(displayarea);
            page1->setVisible(true);
            sheet->addPage( "Page 2", 1 );
            page2 = new WidgetTabPage(this, IDD_DIALOG2);
            page2->setBounds(displayarea);
            sheet->addPage( "Page 3", 2 );
            page3 = new WidgetTabPage(this, IDD_DIALOG3);
            page3->setBounds(displayarea);
        }
    };

    int SmartWinMain( Application & app )
    {
        WidgetTest1 * test = new WidgetTest1();
        test->initAndCreate();
        return app.run();
    }

     
    • Stephan

      Stephan - 2006-07-25

      I forgot to post my modifications of WidgetTabSheet.h! You just add two new pulic functions:

              /// Retrieves the bounding rectangle for the specified tab in a tab control.
              /** The bounding rectangle of a selected tab header.
                */
              bool getItemRect( int nItem, RECT* rect );

              /// Retrieves the bounding rectangle for the display area of a tab control.
              /** The display area of a tab control is the area in which an application displays the current page. Typically, an application creates a child window or dialog box, setting the window size and position to fit the display area.
                */
              SmartWin::Rectangle getDisplayRect( RECT* rect = NULL);

      I know that the following code is not the best, but I was in hurry when I create it:

          template< class Parent, class WidgetMessageMapType >
          bool WidgetTabSheet< Parent, WidgetMessageMapType >::getItemRect( int nItem, RECT* rect )
          {
              if(rect == NULL) return false;
              return (bool)sendWidgetMessage( this->Widget::itsHandle, TCM_GETITEMRECT, (WPARAM &)nItem , (LPARAM &)rect );
          }

          template< class Parent, class WidgetMessageMapType >
          SmartWin::Rectangle WidgetTabSheet< Parent, WidgetMessageMapType >::getDisplayRect( RECT* rect )
          {
              RECT rc;
              RECT itemRect;
              getItemRect(0, &itemRect);
              if(itemRect.left < 0 || itemRect.top < 0 || itemRect.right < itemRect.left || itemRect.bottom < itemRect.top) return SmartWin::Rectangle(0,0,0,0);
              POINT pt;
              GetWindowRect(this->itsHandle, &rc);
              pt.x = rc.left;
              pt.y = rc.top;
              ScreenToClient(this->itsParent->handle(), &pt);
              rc.left = pt.x;
              rc.top = pt.y;
              pt.x = rc.right;
              pt.y = rc.bottom;
              ScreenToClient(this->itsParent->handle(), &pt);
              rc.right = pt.x;
              rc.bottom = pt.y;
              SendMessage(this->itsHandle, TCM_ADJUSTRECT, (WPARAM)FALSE, (LPARAM)&rc);
              struct SmartWin::Rectangle res((LONG)(rc.left - 1), (LONG)(rc.top + itemRect.bottom), (LONG)(rc.right - (rc.left - 1)), (LONG)(rc.bottom - (rc.top + itemRect.bottom)));
              if(rect != NULL) {
                  rect->left = rc.left - 1;
                  rect->top = rc.top + itemRect.bottom;
                  rect->right = rc.right;
                  rect->bottom = rc.bottom;
              }
              return res;
          }

       
    • Thomas Hansen

      Thomas Hansen - 2006-07-25

      This is really cool stuff, only problem with the code is that it diverges too much from the main "philosophy" of SmartWin (like passing pointers to RECT structures instead of returning them as objects)
      Also your previous code was truly great and nifty, problem here is that many of those HANDLE objects you return needs cleaning when going out of scope and therefor should be wrapped inside other classes and probably returned as boost::shared_ptr to guarantee cleaning of them etc...

      It's really hard (and ALOT of work) for us to make it fit into the SmartWin++ model, and all though I'd really LOVE to do it I can just not find the time for doing that conversion...
      (Busy man, 2 commercial life releases now within the next 3-6 months)

      If you create for instance a class called Icon something (check the Bitmap class) and a typedef to a IconPtr (check the BitmapPtr) and create RAII semantics (google for Resource Aquisition Is Initialization) and in other ways uses the SmartWin "way" like for instance SmartWin::Rectangle and returning values (where you can) instead of passing in pointers etc. (look at getSize() in AspectSize.h) it's VERY easy to add your code into the CVS and have it become a part of SmartWin, otherwise we'll hope someone else has the time to make your code fit the SmartWin model in order to get it into the CVS... :(

      It's really great with features, but once you stuff features into a library you're kind of stating that "this code will always be backwards compatible" etc which is difficult to do with most of your code, especially since it contains a lots of pitfalls. (especially for newbies)

      Me and you might know that we should clean up our HICON handles, but a newbie in C++/Windows API wouldn't know such things and therefor would be pretty frustrated when his icon editor was being shutdown by the system for consuming all memory...

      Also if you MUST pass pointers the "SmartWin model" prefers passing by reference instead of raw pointers...

      If you clean it up I'd be more then willing to spend an hour or two on checking it out and formatting doxygen comments etc for it, but as it is know it's just too much work for me to fit into my schedule...

      PS!
      I hope I didn't discourage you, you're doing great work and I really appreciate it, many people have probably already benefitted from your work! :)

      PS2!
      Also if you could modify the existing files (and/or add new ones) and pass them to me by email it would also make life easier for me... ;)

      PS3!
      This is in fact right up my ally, within some 2-4 months I'm gonna start working with a localized Windows Mobile application using (off course) SmartWin and I need this stuff myself, so it's really great to see others doing a job in this area too! :)

      .t

       
      • Nobody/Anonymous

        Actually, there is a Icon class already :)

         
        • Thomas Hansen

          Thomas Hansen - 2006-07-26

          Totally true... (...blush...!)
          That class is a pretty good example of RAII btw...

          .t

           
    • Stephan

      Stephan - 2006-07-27

      Ok, I try to write rescource objects (classes) and change the functions to "smartwin style" ;) I prefer pointer because it's not difficult to port it to mobile devices. Because WinCE < 4.0 has NO EXEPTIONS!

      P.S.: I have no time for the next two weeks because of buisness, but then I can add more functions to smartwin.

       

Log in to post a comment.