SEMI - E95 GUI 개발 방법
사실, HMI 와 여러 산업계, 즉, 통신 체계관리나, 원자력, 발전소, 수자원 관리등에서 사용하는 SCADA 시스템의 GUI 는 이전에는 외산이 많았다. 아직도 그렇기는 하지만, 이런 가운데, 반도체도 90 년대 후반부터 국산화가 여러 분야들 처럼 국내 개발이 진행되어 왔고, KAIST 에서 클러스터 개념의 장비들을 위해, 스케쥴러를 개발하기도 했다.
여러 제품이 나와 있는 상황에서, 그리고, 어플리케이션에서, FA, 데이터관리, 프로세스관리, 하드웨어 드라이브까지 너무 많은 것을 다뤄야하는 분야이기도 하지만, 까다롭기는 GUI 또한 만만치 않다. 키오스크 개념의 인터페이스를 요구하는데다. 오퍼레이터를 위한 배려도, 채터링까지도, 자잘한 것을 모두 요구하는 것이니...
그러다 보니, 반도체 업계의 이런 GUI 요구 사항과 기술 요건은 표준화가 잘 된 편이다. SEMI 규정은 기술적으로는 진보한 것이라 할 수 없지만, 규정 그 자체는 잘 정의하고 있고, 개발자에게 필요한 skill information 을 전달하기에 충분하다.
혹자는 Visual Studio 6.0 C++ 에서 이러한 GUI 를 만들기 어렵다고 하지만, 정말 잘만들어진 com 기반의 체계개발이 아니라면, MDI 와 CDialogBar 로 인터페이스 요건을 맞출 수 있고, 여러 formview 와 tabbed view 를 childframe 에 넣어서 구현할 수 있다. 물론, 자잘한 버튼과 그래프등을 위한 CWnd 를 상속한 컨트롤을 만들어 활용하는 것도 좋은 방법이다. 이것은 매번 ActiveX 를 사용하는 친구들을 보면서 느낀 것이지만, 너무 순수하게 ActiveX 를 View 나 FormView 에 포장해서 나두는 것 같아서 이다. (차라리, 스스로 CWnd 를 상속한 클래스를 만들고, 거기에 필요한 컨트롤을 넣어서, 여러 객체를 자신이 만든 객체 클래스를 여러개 인스턴스화해서, 사용해보면, 많은 편의점이 생길 텐데도 말이다.)
아무튼, Visual Studio 2008 C++ 와 Feature Pack 에서 많은 시간을 소비한 결과 Visual Studio 6.0 과 CDialogBar 가 E95 GUI 사양을 만족하는 GUI Layout 작성에는 유리하다. 왜냐면, 해보면 알겠지만, BCGSoft 의 확장 MFC 에서는 몇가지 고질적인 문제와 확장 MFC 자체를 서브클래싱해야하는 부분도 있다. 예로, CDockablePane 과 CPaneDialog 를 예로 들면, CPaneDialog 는 Gripper 를 없애기가 쉽지 않다. Fixed size 로 하기도 솔루션이 쉽지않다. CDockablePane 에 CDailogBar 언져서 판넬을 구현할 수 있지만, 이또한 SetMinSize 는 잘 적용할 수 있으나, 문제는 SetResizeMode 가 있어도 생각하는 것과 같지 않다. Layout 에 맞게 크기 고정이 쉽지 않고, 솔루션은 상속해서 만들어보는 것, 그러나, 만들어봐도, 스킨 적용이 CDialogBar 는 되지 않는다. Docking 시 오른쪽 외쪽 사이드 바와 아래쪽 바의 겹칩이 사이드바의 설정을 조정해서 번거롭게 처리해야할 부분이 있다. 전체적으로 디자인은 예쁘게 나올 수 있을 것 같지만, 잘 되지 않는다. 확장 MFC 의 리소스가 부족한 것은 기술 문서가 구하기 어려운 것이고, codejoke 나 Profuis 와 유사하기는 하지만, 편의적인 부분과 컨트롤 구현부분에서는 BCGSoft 가 앞선다고 말할 수는 없다. 기존 MFC 를 잘 가꿨지만, 돈을 주고 산다면, CodeJoke 에 마음이 더가고, 화려하고, 다양한 기술면에서는 Profuis 에서 얻고 싶다.
아무튼, Visual Studio 6.0 엣 MDI 를 이용해 다음과 같이 만들면 된다. 너무 어렵게 생각하면, 아무것도 안된다. 다음에는 더 꾸며 보겠지만, 결국, GUI 엔진에 더 많은 관심과 정력을 쏟을 것 같다.
#pragma once #include "resource.h" // CPanelTitleBar dialog class CPanelTitleBar : public CDialogBar { DECLARE_DYNAMIC(CPanelTitleBar) public: CPanelTitleBar(CWnd* pParent = NULL); virtual ~CPanelTitleBar(); // Dialog Data enum { IDD = IDD_DIALOGBAR_PANEL_TITLE }; CSize m_size; BOOL m_bForceSize; BOOL m_bDragging; BOOL Create(CWnd* pParentWnd, UINT nID, CSize initsize); virtual CSize CalcFixedLayout(BOOL bStretch, BOOL bHorz); protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support afx_msg LONG OnInitDialog(UINT wParam, LONG lParam); afx_msg void OnPanelTitleButtonsUpdateCmdUI(CCmdUI* pCmdUI); DECLARE_MESSAGE_MAP() public: afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); afx_msg void OnLButtonDblClk(UINT nFlags, CPoint point); afx_msg void OnLButtonDown(UINT nFlags, CPoint point); afx_msg void OnMouseMove(UINT nFlags, CPoint point); afx_msg void OnLButtonUp(UINT nFlags, CPoint point); afx_msg void OnBnClickedButton1(); }; |