Solved

Making a TTY window in an MDI App

Posted on 1999-01-29
19
382 Views
Last Modified: 2013-11-20
I have an MDI app that does some talking to the serial port and I was wondering how I could go about using the child window that gets created when I start the app as a TTY window that could monitor all the serial port traffic.  Basically, what are some ideas of how I could display the data that I send/recieve to the Child Window?
0
Comment
Question by:kirts
  • 12
  • 7
19 Comments
 
LVL 1

Expert Comment

by:jim_pettinato
ID: 1328492
Easy. Make the child window a CFormView class. Create a resource for the form view that contains an edit control. Size it to fit the window. Set the edit control style for multiline and want return. Then, create a member variable CString that will store the data for the control and allow you to modify it. You can get quite fancy. Here is some code I did, that allows for input and output. You will have to change the code that does the transmit/receive of data - my comm stuff is done via a custom class. Just modify that part to use your gozintas/gozoutas.

class CTerminalView : public CFormView
{
   DECLARE_DYNCREATE(CTerminalView)

protected:
   CTerminalView();          
   BOOL initialized;

// Form Data
public:
      //{{AFX_DATA(CTerminalView)
      enum { IDD = IDD_EMULATOR };
      CString m_cmdData;
        CString m_prevData;
        CString m_logData;
      //}}AFX_DATA

// Attributes
public:

// Operations
public:

// Implementation
protected:
      virtual ~CEmulatorView();
      virtual void DoDataExchange(CDataExchange* pDX);    
      virtual void OnUpdate(CView* pSender, LPARAM lHint, CObject* pHint);
   virtual void OnInitialUpdate();

      // Generated message map functions
      //{{AFX_MSG(CEmulatorView)
      afx_msg void OnDataChange();
        afx_msg void OnMenuCommand(int menuID);
      //}}AFX_MSG
      DECLARE_MESSAGE_MAP()
};



#ifdef _DEBUG
#undef THIS_FILE
static char BASED_CODE THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CTerminalView

IMPLEMENT_DYNCREATE(CTerminalView, CFormView)

CTerminalView::CTerminalView()
      : CFormView(CTerminalView::IDD)
{
      //{{AFX_DATA_INIT(CTerminalView)

      //}}AFX_DATA_INIT

   // Get pointer to app so we can access active communications protocol
      app = (AccuMateApp *) AfxGetApp();
   initialized = FALSE;
}

CTerminalView::~CTerminalView()
{
   // inform main frame terminal window closing so it can reset its member ptr
   ((CMainFrame *) AfxGetApp()->m_pMainWnd)->m_pEmulatorWindow=NULL;
}

void CEmulatorView::OnInitialUpdate()
{
   GetParentFrame()->RecalcLayout();
   ResizeParentToFit(FALSE);
   initialized = TRUE;
   CString title;
   title = "Terminal Window - " + GetDocument()->GetTitle();
   GetParentFrame()->SetWindowText(title);
   SetFocus();
}

void CTerminalView::OnUpdate(CView*, LPARAM, CObject*)
{
   if (!initialized)
      OnInitialUpdate();
       m_prevData = m_cmdData = "";
      UpdateData(FALSE);  // set the data into the controls
}

void CTerminalView::DoDataExchange(CDataExchange* pDX)
{
      CFormView::DoDataExchange(pDX);
      //{{AFX_DATA_MAP(CTerminalView)
      DDX_Text(pDX, IDC_COMMAND, m_cmdData);
   DDX_Text(pDX, IDC_LOG, m_logData);
      //}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CTerminalView, CFormView)
      //{{AFX_MSG_MAP(CTerminalView)
      ON_EN_CHANGE(IDC_COMMAND, OnDataChange)
      //}}AFX_MSG_MAP
        ON_COMMAND_RANGE(ID_COMMAND_TABLE_START,ID_COMMAND_TABLE_END,OnMenuCommand)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CTerminalView message handlers

void CTerminalView::OnDataChange()
{
      if (!UpdateData())
            return;

      CMyDoc* pDoc = GetDocument();

      BOOL bUpdate = FALSE;
      if (m_cmdData != m_prevData)
      {
      int length;
      if ((length = m_cmdData.Find(CR)) >= 0)
       {
         CWaitCursor hgCursor;
         CString cmd, rsp, buf;

         cmd = m_cmdData.Left(length);
         m_cmdData = "";
         UpdateData(FALSE); // update edit control (blank out command control)

         // set current position of log control to end of text
         ((CEdit *) GetDlgItem(IDC_LOG))->SetSel(m_logData.GetLength(),
                                                      m_logData.GetLength());

         hgCursor.Restore();
         if (!app->ActiveProtocol()->XmitPacket(cmd, cmd.GetLength()))
            {
              app->ActiveProtocol()->ComErrBox();
              return;
            }

         if (app->ActiveProtocol()->ReceivePacket(rsp.GetBuffer(80)) != COM_NO_ERROR)
           {
             app->ActiveProtocol()->ComErrBox();
             rsp = app->ActiveProtocol()->ComErrMsg(app->ActiveProtocol()->LastError());
           }

         buf.Format("%-32.32s %-40.40s\r\n",(LPCTSTR) cmd, (LPCTSTR) rsp);

         // add buf as new line to log control
         m_logData += buf;

         // delete log data from the control a line at a time until within limit
         while (length > 1024)
            m_logData = m_logData.Right(m_logData.GetLength() - m_logData.Find('\r'));

         UpdateData(FALSE);    // update log control with command + response

         // NOTE: Update cursor position so that last line added is visible
         ((CEdit *) GetDlgItem(IDC_LOG))->SetSel(m_logData.GetLength(),
                                                      m_logData.GetLength());
         m_prevData = m_cmdData;
       }
      else
       { //NOTE: do command parse here... help hints, auto-uppercase, etc.
       }
      }
   // update any other views if we did anything that might affect them
      if (bUpdate) // if the document stored data call SetModifiedFlag here
            pDoc->UpdateAllViews(this);
}




The following entry must go into your project's ".RC" file:

IDD_EMULATOR DIALOG 3, 4, 283, 199
EXSTYLE WS_EX_MDICHILD
STYLE WS_CHILD
FONT 10, "Courier"
{
 CONTROL "", IDC_COMMAND, "edit", ES_LEFT | ES_MULTILINE | ES_AUTOVSCROLL | ES_OEMCONVERT | ES_WANTRETURN | WS_CHILD | WS_VISIBLE | WS_BORDER | WS_TABSTOP, 8, 8, 268, 12
 CONTROL "", IDC_LOG, "edit", ES_LEFT | ES_MULTILINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_READONLY | ES_WANTRETURN | WS_CHILD | WS_VISIBLE | WS_BORDER, 8, 24, 268, 164, WS_EX_NOPARENTNOTIFY
}

0
 

Author Comment

by:kirts
ID: 1328493
Actually, that was way more than I was wanting/needing to know.  I think you may have missed the point of the question. Sorry if I was unclear.  Basically here's the gist:  I have an MDI app.  When I open it up there's the that first child window that opens when the app starts.  When I send data across the serial port, I also copy that data to a file.  At the same time as I send the data(i.e. copy it to the file) I want to then open that file and display the data to the child window that is open.  Seeing as I'm not an expert at MFC yet, I've been basically trying to half ass my way around getting this done as simply as possible.  I have attached what code I have so far for this part of the task.  For some reason, when I use SetWindowText(), it will display the stuff I want to display in the window, but there are no spaces and no way to really format the position of the text on screen.  I am trying to get TextOut() to work but I get an assert error saying ASSERT(m_hDC != NULL).  Could you possibly shed some light on this for me?  The SendAllData() and the OnDraw() functions are the ones you want to pay attention to.  Thanks a lot.



//GLOBALS
EPDlg ep_dialog;      //EP CONTROLS DIALOG BOX OBJECT
MotorDialog motor_dialog;   //MOTOR CONTROLS DIALOG BOX OBJECT

/////////////////////////////////////////////////////////////////////////////
// CWinView

IMPLEMENT_DYNCREATE(CWinView, CEditView)

BEGIN_MESSAGE_MAP(CWinView, CEditView)
      //{{AFX_MSG_MAP(CWinView)
      ON_COMMAND(EP_CONTROLS_OPEN, OnEPControlsOpen)
      ON_COMMAND(MOTOR_CONTROLS_OPEN, OnMotorControlsOpen)
      ON_COMMAND(DIALOG_SAVE, OnSaveAll)
      ON_COMMAND(SAVE_EP_DATA, OnSaveEpData)
      ON_COMMAND(SAVE_MOTOR_DATA, OnSaveMotorData)
      ON_COMMAND(SEND_ALL_DATA, OnSendAllData)
      //}}AFX_MSG_MAP
      // Standard printing commands
      ON_COMMAND(ID_FILE_PRINT, CEditView::OnFilePrint)
      ON_COMMAND(ID_FILE_PRINT_DIRECT, CEditView::OnFilePrint)
      ON_COMMAND(ID_FILE_PRINT_PREVIEW, CEditView::OnFilePrintPreview)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CWinView construction/destruction

CWinView::CWinView()
{
      // TODO: add construction code here

}

CWinView::~CWinView()
{
}

BOOL CWinView::PreCreateWindow(CREATESTRUCT& cs)
{
      // TODO: Modify the Window class or styles here by modifying
      //  the CREATESTRUCT cs

      BOOL bPreCreated = CEditView::PreCreateWindow(cs);
      cs.style &= ~(ES_AUTOHSCROLL|WS_HSCROLL);      // Enable word-wrapping

      return bPreCreated;
}

/////////////////////////////////////////////////////////////////////////////
// CWinView drawing

void CWinView::OnDraw(CDC* pDC)
{
      char string[100];
      FILE* dataFile;
      int i = 0;
      dataFile = fopen("tty.dat", "r");

      CWinDoc* pDoc = GetDocument();
      ASSERT_VALID(pDoc);

      while ( feof(dataFile) == 0 )
      {
            fgets(string, 100, dataFile);
            pDoc->TTYstring = string;
            SetWindowText(pDoc->TTYstring);
      
            //pDC->TextOut(0,i,pDoc->TTYstring);
      //      ++i;
      }//END WHILE

      fclose(dataFile);

      
      
// TODO: add draw code for native data here
}

/////////////////////////////////////////////////////////////////////////////
// CWinView printing

BOOL CWinView::OnPreparePrinting(CPrintInfo* pInfo)
{
      // default CEditView preparation
      return CEditView::OnPreparePrinting(pInfo);
}

void CWinView::OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo)
{
      // Default CEditView begin printing.
      CEditView::OnBeginPrinting(pDC, pInfo);
}

void CWinView::OnEndPrinting(CDC* pDC, CPrintInfo* pInfo)
{
      // Default CEditView end printing
      CEditView::OnEndPrinting(pDC, pInfo);
}

/////////////////////////////////////////////////////////////////////////////
// CWinView diagnostics

#ifdef _DEBUG
void CWinView::AssertValid() const
{
      CEditView::AssertValid();
}

void CWinView::Dump(CDumpContext& dc) const
{
      CEditView::Dump(dc);
}

CWinDoc* CWinView::GetDocument() // non-debug version is inline
{
      ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CWinDoc)));
      return (CWinDoc*)m_pDocument;
}
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CWinView message handlers

void CWinView::OnEPControlsOpen()
{

      ep_dialog.Create(EP_DIALOG, NULL);
      ep_dialog.ShowWindow(SW_SHOW);

}

void CWinView::OnMotorControlsOpen()
{

      motor_dialog.Create(MOTOR_DIALOG, NULL);
      motor_dialog.ShowWindow(SW_SHOW);
      
}


void CWinView::OnSaveAll()
{
      
      ep_dialog.UpdateData(TRUE);
      ep_dialog.UpdateSaveFile();

      motor_dialog.UpdateData(TRUE);
      motor_dialog.UpdateSaveFile();
}

void CWinView::OnSaveEpData()
{
      ep_dialog.UpdateData(TRUE);
      ep_dialog.UpdateSaveFile();

}

void CWinView::OnSaveMotorData()
{

      motor_dialog.UpdateData(TRUE);
      motor_dialog.UpdateSaveFile();
      
}

void CWinView::OnSendAllData()
{
      CDC* pDC;
      CWinDoc* pDoc = GetDocument();
      ASSERT_VALID(pDoc);
      ep_dialog.SendDataToEngine();

      OnDraw(pDC);


}      

0
 
LVL 1

Accepted Solution

by:
jim_pettinato earned 140 total points
ID: 1328494
Okay... now I see what you are looking for. All you really need to do is understand how to interact with an edit view. What is not obvious is it really is just a wrapper for an edit control, so you interact with the _control_ to get text into/out of the view. You use the CEditView::GetEditCtrl() member function to access the edit control embedded in the view. Then you use the CEditCtrl member functions as you would for an edit control on a dialog box.

So, in your CWinView::OnDraw(), you can just do the following:

int startPos, endPos;
CEdit *ctrl = GetEditCtrl();

ctrl->SetSel(0,-1, TRUE);  // select all text in control
ctrl->ReplaceSel(string);  // write first line
ctrl->SetSel(0,-1, TRUE);  // again select all text
ctrl->GetSel(&startPos, &endPos);  // get the start/end of text
ctrl->SetSel(endPos, endPos);     // select an empty region at end of text
ctrl->ReplaceSel(string2);  // insert string2 at end of text



Good luck. Note: you may also want to do things like select a non-proportional font into the edit view so it 'looks' more like a terminal.
0
 

Author Comment

by:kirts
ID: 1328495
I won't be able to try this out for maybe a week so I'll let you know how it goes sometime then and give you your points.  
0
 

Author Comment

by:kirts
ID: 1328496
When I try to that CEdit ctrl = GetEditCtrl() I get this error:
error C2440: 'initializing' : cannot convert from 'class CEdit' to 'class CEdit'
        No copy constructor available for class 'CEdit'

What's the scoop on that?
0
 

Author Comment

by:kirts
ID: 1328497
Here's the code I have so far for what you said and the compiler hates it.

void CWinBlueJayFlexorView::OnDraw(CDC* pDC)
{
      char string[100];
      FILE* dataFile;
      int i = 0;
      dataFile = fopen("tty.dat", "r");

      CWinBlueJayFlexorDoc* pDoc = GetDocument();
      ASSERT_VALID(pDoc);

      while ( feof(dataFile) == 0 )
      {
            fgets(string, 100, dataFile);
            int startPos, endPos;
            CEdit* ctrl;
            ctrl = GetEditCtrl();

            ctrl->SetSel(0,-1, TRUE);  // select all text in control
            ctrl->ReplaceSel(string);  // write first line
            ctrl->SetSel(0,-1, TRUE);  // again select all text
          ctrl->GetSel(startPos, endPos);  // get the start/end of text
            ctrl->SetSel(endPos, endPos);     // select an empty region at end of text
            ctrl->ReplaceSel(string);  // insert string2 at end of text

            //pDoc->TTYstring = string;
      //      SetWindowText(pDoc->TTYstring);
      
            //pDC->TextOut(0,i,pDoc->TTYstring);
      //      ++i;
      }//END WHILE

      fclose(dataFile);

      
      
// TODO: add draw code for native data here
}
0
 

Author Comment

by:kirts
ID: 1328498
Here's the code I have so far for what you said and the compiler hates it.

void CWinBlueJayFlexorView::OnDraw(CDC* pDC)
{
      char string[100];
      FILE* dataFile;
      int i = 0;
      dataFile = fopen("tty.dat", "r");

      CWinBlueJayFlexorDoc* pDoc = GetDocument();
      ASSERT_VALID(pDoc);

      while ( feof(dataFile) == 0 )
      {
            fgets(string, 100, dataFile);
            int startPos, endPos;
            CEdit* ctrl;
            ctrl = GetEditCtrl();

            ctrl->SetSel(0,-1, TRUE);  // select all text in control
            ctrl->ReplaceSel(string);  // write first line
            ctrl->SetSel(0,-1, TRUE);  // again select all text
          ctrl->GetSel(startPos, endPos);  // get the start/end of text
            ctrl->SetSel(endPos, endPos);     // select an empty region at end of text
            ctrl->ReplaceSel(string);  // insert string2 at end of text

            //pDoc->TTYstring = string;
      //      SetWindowText(pDoc->TTYstring);
      
            //pDC->TextOut(0,i,pDoc->TTYstring);
      //      ++i;
      }//END WHILE

      fclose(dataFile);

      
      
// TODO: add draw code for native data here
}
0
 

Author Comment

by:kirts
ID: 1328499
My only guess is that there is no assignment operator defined for the CEdit class.  That doesn't make any sense though because what good would GetEditCtrl() be (seeing as it returns a reference to a CEdit object) if you can't set anything equal to the returned reference???
0
 
LVL 1

Expert Comment

by:jim_pettinato
ID: 1328500
Sorry, the example code I gave you was off the top of my head... your last message made it obvious. The GetEditCtrl() method returns a _reference_, not a pointer. Hence you have to declare the variable as a reference, ie. :

CEdit& ctrl = GetEditCtrl();

ctrl.SetSel(...)     // use the . operator instead of -> for reference
0
Free Trending Threat Insights Every Day

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

 

Author Comment

by:kirts
ID: 1328501
Ok, here's a new approach to this problem that I need help with.  I am scrapping that whole file idea.  So my new question is this: If I have a dialog box class that has a SendDataToSerialPort function, how can I go about storing the data the that I send(without using a file), and then some how pass that data to my CProgramView class so that I can update the child window with that data.  Basically it's the same question as before, except I want to do it without using files.



0
 
LVL 1

Expert Comment

by:jim_pettinato
ID: 1328502
Where the data comes from, or is stored, has nothing to do with how it is displayed in the view class. The answer I gave you should work no matter where the string info comes from. How big is your data? If a typical transmission is less than, say, a couple hundred characters, I would just pass the info in a CString. You can set a max on the amount of data the edit view 'remembers'. Once the dialog sends out some data, tack that data on the end of the view class, and discard any 'old' info if the edit control is 'full'. Add a method to your view class that looks something like this:

CTerminalView::AddText(CString& newText)
{
  CEdit& ctrl = GetEditCtrl();
  // add the new text to the end

  ctrl->SetSel(0,-1, TRUE);  // select all text in control
  ctrl->GetSel(startPos, endPos);  // get selection
  ctrl->SetSel(endPos, endPos);    // set selection at end
  ctrl->ReplaceSel(newText);  // insert string2 at end of text
  // limit size of text in edit control
  ctrl->SetSel(0,-1, TRUE);  // select all text in control
  ctrl->GetSel(startPos, endPos);  // get selection
  if (endPos > MAX_BUFSIZE)
    {  // delete excess 'old' data from buffer
       ctrl->SetSel(0, endPos - MAX_BUFSIZE);
       ctrl->ReplaceSel("");
    }  
}

I don't know where your dialog is called from; whether is has a pointer to your terminal view class, etc. There are lots of things that would affect how this might work best. Do you have to have a separate dialog class doing the transmitting? Can the View class do the transmitting? I guess I need to see what you have so far to know what the best approach would be.
0
 

Author Comment

by:kirts
ID: 1328503
The dialog class does the transmitting and I would very much prefer to keep it that way.  How would I go about getting a pointer to the current CView object of my program I guess would be a valid question.  I would like to be able to call a function within my Dialog class that does something like this

CDialog::SendDataToPort()
{
  UpdateData(); //get the data from the dialog
  //Send the data to the port (i already know how to do this)
  //Somehow get a pointer to the current CView object
  //Display the data to the current view
}


0
 
LVL 1

Expert Comment

by:jim_pettinato
ID: 1328504
There are several ways to get this....

A method that should always work:

 CWinView *myView = (CWinView *)AfxGetMainWnd()->GetActiveView();


Another approach may be to just 'store' a pointer to the view when you create the dialog. Add a CWinView *m_view public member to the dialog and assign it before you call the dialog's DoModal(). I'm assuming the view is active when the dialog is opened. Then in your SendDataToPort func you could just access the view via the m_view member.

Other ways: the CDocument class has a GetActiveView() member; this is one way to get a pointer to the view. Is this an MDI or SDI app? Are you launching the dialog box from the view's code, or from the main window's code, or where?


0
 

Author Comment

by:kirts
ID: 1328505
It's an MDI app and I'm launching the dialog box from the view's code.
0
 

Author Comment

by:kirts
ID: 1328506
I tried this in my SendDataToPort function:
CWinBlueJayFlexorView *myView =
(CWinBlueJayFlexorView *)AfxGetMainWnd();
string = "hello world";
CEdit& ctrl = myView->GetEditCtrl();
ctrl.SetSel(0,-1, TRUE);  // select all text in control
ctrl.ReplaceSel(string);  // write first line
ctrl.SetSel(0,-1, TRUE);  // again select all text
ctrl.SendMessage(WM_PAINT);  //this i am not sure about

Everything compiles correctly, but nothing ever gets displayed to the view when I try this.  How do I go about getting the view to update itself with the new text?  I thought maybe sending it a WM_PAINT message would work, but no dice.
0
 
LVL 1

Expert Comment

by:jim_pettinato
ID: 1328507
>>I tried this in my SendDataToPort function:
>> CWinBlueJayFlexorView *myView =
>> (CWinBlueJayFlexorView *)AfxGetMainWnd();
>> string = "hello world";

The AfxGetMainWnd() function returns a pointer to the frame window, not the view.

You need to use

(CWinBlueJayFlexorView *) myView =
   (CWinBlueJayFlexorView *) AfxGetMainWnd()->GetActiveView();

Your view class _is_ derived from CEditView, right?

You will not need to send a paint message. The functions to update the selection cause the control to repaint itself. With the changes above, what you have _should_ work.



However, if you are still having problems, we can take the other approach, which is store a pointer to the view in the dialog, rather than to try and get a pointer to it using the AfxGetMainWnd()->GetActiveView() stuff. If you are indeed creating the dialog from the view's code, it is as simple as adding the following:

 in your dialog class' header file, add the following member:

    CEditView *m_view;

when you create the dialog box (in the view's code):

    CMyDialog dlg;
     
    dlg.m_view = this;
    dlg.DoModal();

 
Then, in your dialog's code, you can just use the m_view member to get the edit control like this:

   CEdit& ctrl = m_view->GetEditCtrl();




Okay, I think it's time you give me some points here. I'll continue to attempt to assist you if you still need it.


0
 

Author Comment

by:kirts
ID: 1328508
Yeah, you're very correct about the points thing, sorry.  I'll give the new suggestions a try when I get some more time.
0
 

Author Comment

by:kirts
ID: 1328509
Ok, that definitely helped.  I can get the data where I want to be on the child window by getting the DC and doing a DC->TextOut.
I have my Child windows as members of CEditView therefore(supposedly) making the view automatically scrollable.  When I open a text doc, it works fine, I can scroll the doc.  But when I do a DC->TextOut and I put the text somewhere past the end of the view it won't let me scroll down and see it.  What's the scoop on that?
0
 
LVL 1

Expert Comment

by:jim_pettinato
ID: 1328510
The edit control has no idea the text is being drawn if you use the GDI functions (i.e., TextOut()) to draw the text. If you do not modify the appearance of the edit view by modifying the text in the control, it cannot possibly handle scrolling the text. TextOut() does nothing but paint pixels in a client area. Once it is drawn, it is forgotten. If it is not entirely within the client window rectangle, it is 'clipped' to the visible area (in other words, if you are drawing outside the visible area, it is never really drawn at all).
The edit control 'stores' the text in a member CString variable. Hence, it can 'redraw' that portion of the text that was previously not visible.
0

Featured Post

6 Surprising Benefits of Threat Intelligence

All sorts of threat intelligence is available on the web. Intelligence you can learn from, and use to anticipate and prepare for future attacks.

Join & Write a Comment

Introduction: Load and Save to file, Document-View interaction inside the SDI. Continuing from the second article about sudoku.   Open the project in visual studio. From the class view select CSudokuDoc and double click to open the header …
Introduction: The undo support, implementing a stack. Continuing from the eigth article about sudoku.   We need a mechanism to keep track of the digits entered so as to implement an undo mechanism.  This should be a ‘Last In First Out’ collec…
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.
You have products, that come in variants and want to set different prices for them? Watch this micro tutorial that describes how to configure prices for Magento super attributes. Assigning simple products to configurable: We assigned simple products…

762 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

18 Experts available now in Live!

Get 1:1 Help Now