'MFC'에 해당되는 글 4건

  1. 2008.04.11 Several Reasons to hate MFC by Dansoonie
  2. 2008.02.24 [VC++] Window의 초기 크기와 위치 정해주기 1 by Dansoonie
  3. 2008.01.31 [VC++ 6.0] Having Trouble with CSpintButtonCtrl??? by Dansoonie
  4. 2007.11.21 Serial Port 통신 MFC로 구현하기... 7 by Dansoonie
Personally, I think MFC failed to grasp the concept of the Object-Oriented Programming paradigm.
MFC provides poor data abstraction and encapsulation. And here are my personal opinions what led to that conclusion.


1. I guess I am never going to understand how the Doc/View Architecture is supposed to work. Especially the part how Documents are created or opened, and how it associates with the views. It involves too much unnecessary details when you can easily implement something similar to the Doc/View architecture by using simple association among classes.

2. What is the difference between Classes that are derived from CDialog, and CFormView. Some of the people who understand MFC better than me might argue with my opinion, but don't they serve the same purpose of displaying whatever there is to? I think I understand the intention of separating the roles of dialogs and views, but I think it was a bad choice. Does the .Net framework distinguish dialog and views?

3. Why are the information of the resources declared in global scope in resource.h and .rc file? Why doesn't the class itself contain the information of the resources? Of course it is possible to make the class contain the information of the resources it contains by using DLGTEMPLATE structure. Creating the dialog template dynamically in memory and loading it at run-time. However, you will have code every single information of each control. For this reason, it is difficult to create static library that contains graphical user interface.

4. I find the MFC library interface to be inconsistent. For example, when parameters of a function must be passed by reference, in some cases, the formal parameter is passed by reference, while the rest uses pointer type parameters.

5. Units differ by the context in which it is being used. Why couldn't they have used pixels for the main unit for every measurement? This really bothers me when I am writing code that creates the dialog template on the fly at run-time.

6. Some features aren't documented on MSDN while Google shows us bunch of undocumented features. Why is that? My guess is that the undocumented features were supposed to be hidden. However, many parts of the undocumented tricks and features can be found on the web.

7. While debugging, you can actually step into the MFC library. What is the intention of letting that possible? I suspect that the library code can be accidentally altered by the programmer. Although it is something which must have been avoided, I cannot imagine debugging my program without stepping into the library. If debugging was only possible by stepping into the library code for some situations, then I think MFC seriously failed to provide nice and neat data abstraction and encapsulation. Or maybe the folks at Microsoft were too lazy to implement exception handling for majority of the possible errors and document them.

8. Simply too complicated...


Yes, MFC is very flexible, hence powerful. But only if you understand every tiny detail correctly. I'm not a very experienced programmer, especially in VC++. That might be the reason why I am complaining about the issues above. The opportunity to work with MFC made me humble and I actually found out that there are many things that I don't know well yet that I used to think I knew well. Some things I pointed out might not be true due to my lack of knowledge and understanding. However, many people may agree that MFC or probably WIN32 API is hard for starters. Or maybe I'm too accustomed to OOP that I cannot stand the complexity of MFC (Although MFC are class based, and uses the OOP paradigm most of you would agree that Java and C# are more OOP oriented, wouldn't you?).

I would like to hear about other people's opinion on MFC. Its strengths and weaknesses. Are you up for it or not???
Posted by Dansoonie
Windows 용 응용프로그램을 만들 경우에, console 프로그램이 아닌경우에는 실행시에 window의 초기 위치와 크기를 정해주고 싶은 경우가 있을것이다. 나는 몇일전에 있었다~

쉽게 할 수 있는 방법을 정리하고자 한다.

우선 코드를 논하기에 앞서서 내가 사용한 방법을 간략히 설명하자면, MainFrame class에 WM_SHOWWINDOW message에 대한 event handler를 만들어주어 그 안에서 WINDOWPLACEMENT structure를 이용했다.

void CMainFrame::OnShowWindow(BOOL bShow, UINT nStatus)
{
    CFrameWnd::OnShowWindow(bShow, nStatus);
    // 창이 보이는 시점이 프로그램 실행 후 최초인지 판별하기 위한 변수
    static bool once = true;  

    // 창이 보이는 시점이 프로그램 실행후 최초인지 검사하는 구문
    if (bShow && !IsWindowVisible() && once) 
    {
       // 프로그램 실행후 이곳은 한번만 실행되도록 once를 false로...
       once = false;

       // 창의 위치에 대한 정보를 담을 변수 min, max
       // min: 창의 좌측 상단의 좌표
       // max: 창의 우측 하단의 좌표
       // 아래에 사용된 숫자는 임의로 사용한 숫자임
       POINT min, max;
       min.x = 100;
       min.y = 100;
       max.x = 500;
       max.y = 500;
  
       WINDOWPLACEMENT lwp;
       lwp.length = sizeof(WINDOWPLACEMENT);
       lwp.flags = SW_SHOWMINIMIZED | WPF_SETMINPOSITION;
       lwp.showCmd = SW_SHOW;
       lwp.ptMinPosition = min;
       lwp.ptMaxPosition = max;
       lwp.rcNormalPosition = CRect(min, max);
       SetWindowPlacement(&lwp);
    }
}


WINDOWPLACEMENT structure에 대한 구체적인 설명은 MSDN을 참고하시기 바라며...
Visual C++ 6.0 MFC에서의 WINDOWPLACEMENT structure documentation (http://msdn2.microsoft.com/en-us/library/aa253040(VS.60).aspx)

추가적으로 창의 최대 크기 및 최소 크기 지정하는 방법까지 설명하겠다...
Window의 최대 크기 및 최소 크기에 대한 정보를 지정하는 방법은 WM_GETMINMAXINFO message에 대한 event handler를 만들어주는 것이다. 아마도 창의 사이즈가 변경될때 OnGetMinMaxInfo를 불러 창 크기의 최대값과 최소값에 대한 정보를 읽어와 동작에 대한 constraint가 주어지는것 같다...
하지만 이것은 내 생각일뿐... 진실은 저 너머에...ㅎㅎㅎ

void CMainFrame::OnGetMinMaxInfo(MINMAXINFO* lpMMI)

    // 최소 크기일때 가로폭
    lpMMI->ptMinTrackSize.x = 1000;
    // 최소 크기일때 세로폭
    lpMMI->ptMinTrackSize.y = 700;
    // 최대 크기일때 가로폭
    lpMMI->ptMaxTrackSize.x = GetSystemMetrics(SM_CXSCREEN);
    // 최대 크기일때 세로폭
    lpMMI->ptMaxTrackSize.y = GetSystemMetrics(SM_CYSCREEN);
    CFrameWnd::OnGetMinMaxInfo(lpMMI);
}

GetSystemMetrics(SM_CXSCREEN) 및 GetSystemMetrics(SM_CYSCREEN)은 현재 설정된 해상도의 가로폭과 세로폭에 대한 정보를 return해준다. 이 정보를 사용하면 해상도에 따라 적절한 창의 크기 및 위치를 설정해 줄 수 있다. 또한 나의 경우에는 OnGetMinMaxInfo에서 설정해준 창의 최소 크기의 값을 사용하여 창의 위치를 정해줄때 화면 한가운데에 놓이도록 숫자를 입력하였다. 그러기 위한 숫자들은 수학을 잘하는 당신들이 알아서 해보세요~



Posted by Dansoonie
Are you having trouble using the CSpinButtonCtrl in MFC?
Then what kind of trouble are you going through?

In my case, I was having trouble with setting the range of the spin button control. I needed to set the range from 0 to 0xFFFF. The default range of CSpinButtonCtrl is from 0 to 100. And the range can be modified by using the SetRange method. However, the range must be defined within the range -0x8000~0x7FFF inclusive.  Moreover, if I remember correctly, the difference between the max and min of the range must not exceed 0x7FFF. I am pretty sure that not many people would have been happy with this limitation. To overcome this limitation, I guess Microsoft added a method called SetRange32 for the CSpinButtonCtrl. The SetRange32 method has no limits on setting the range within the 32 bit integer range. But does this mean that there absolutely no limitations on using the CSpinButtonCtrl within the 32 bit integer range?
No !!!
I believe another method frequently used in CSpinButtonCtrl among with SetRange is SetPos and GetPos method. Now comes the funny part. Even though you set the range for the CSpinButtonCtrl with SetRange32 method, SetPos and GetPos operates properly within the 12 bit interger range, which is -0x8000~0x7FFF.

After some research I found out that you can get and set the position of the CSpinButtonCtrl by sending UDM_SETPOS32 and UDM_GETPOS32 message to the CSpinButtonCtrl object. So the code will become something like the following...

// Assume that the control ID of the CSpinButtonCtrl is IDC_SPIN
CSpinButtonCtrl spinButtonCtrl;
// set range
spinButtonCtrl.SetRange32(0, 0xFFFF);

// 1. how to set position
// nPos is the new position
// (valid position within the range specified above)
GetDlgItem(IDC_SPIN)->SendMessage(UDM_SETPOS32, 0, nPos);
//2. how to get position
int pos = GetDlgItem(IDC_SPIN)->SendMessage(UDM_GETPOS32, 0, NULL);

The requirements for being able to do this is having comctl.dll version 5.8 or later and commctrl.h. I figured out that the version of my comctl.dll is 5.82. But I had some problems with commctrl.h. At the moment, I have two versions of Visual Studio. Version 6.0 and 2005. The commctrl.h that Visual Studio 2005 refers to has the following lines.

#define UDM_SETPOS32 (WM_USER+113)
#define UDM_GETPOS32 (WM_USER+114)

On the otherhand, the commctrl.h that Visual Studio 6.0 refers to does not define the messages UDM_SETPOS32 and UDM_GETPOS32.

Knowing that the value defined for UDM_GETRANGE32 is WM_USER+112, here is what I did...

// 1. how to set position
// nPos is the new position
// (valid position within the range specified above)
GetDlgItem(IDC_SPIN)->SendMessage(UDM_GETRANGE32+1, 0, nPos);
//2. how to get position
int pos = GetDlgItem(IDC_SPIN)->SendMessage(UDM_GETRANGE32+2, 0, NULL);


On second thought I decided to define my two messages on my own. So I added the two lines that were absent in my commctrl.h in my source code and used UDM_SETPOS32 and UDM_GETPOS32 where I actually send the message to the CSpinButtonCtrl in the code.

On the third thought, I had a better idea. I created my own class derived from CSpinButtonCtrl called CSpinButtonCtrl32. I defined SetPos and GetPos method in the following manner.

#define UDM_SETPOS32 (WM_USER+113)
#define UDM_GETPOS32 (WM_USER+114)

int CSpinButtonCtrl32::SetPos(int nPos)
{
    int prevPos = this->SendMessage(UDM_GETPOS32, 0, NULL);
    this->SendMessage(UDM_SETPOS32, 0, nPos);
    return prevPos;
}

int CSpinButtonCtrl32::GetPos()
{
    return this->SendMessage(UDM_GETPOS32, 0, NULL);
}

And everthing worked just as I wanted. Spin Button Control without much limitations on setting the range and setting/getting the position.


Posted by Dansoonie

요새 회사에서 하고 있는 일이다.

Windows API와 MFC 6.0 으로...
일단 MFC를 평가하자면, 제대로 알고 쓰면 정말 막강한 도구다. 반면 객체지향이라는 패러다임에 썩 들어맞지 않는 모델을 기반으로 개발된것 같다. C++처럼 정말 flexible하게 사용할 수 있다는 장점 이외에는 그다지 소프트웨어 개발 too로써는 큰 장점이 없는것 같다. 예전에는 윈도우즈용 프로그램을 만들기 위해서는 최적의 도구였는지 몰라도 .Net이 나온 이상 MFC 6.0은 사라져야 한다고 생각한다...

MFC를 사용하면서 항상 느끼는 뭔가 정리되지 않은듯한 기분... Java에서 GUI를 프로그래밍을 처음 접할때 느낀 그런기분이랑 비슷하다... 다만 이제는 Java보다 더 조잡한 언어가 있다는 사실을 깨달았다...(개인적인 의견이니 절대 격분하시는 분이 없길 바랍니다)

Message Passing이라는 개념 자체를 잘 이해를 못해서 그런지, 참 어렵다...
C#으로 짜라면 어떻게든 짤 수 있을것 같은데 MFC로는 정말 모르겠다...
우리 회사에서 C#을 무서워 하는 이유는 윈도우즈를 업데이트 하여 .Net Framework를 설치 하지 않으면 돌아가지 않기 때문이다...
그런데 Windows를 업데이트하는것을 왜 두려워 하는지 모르겠다...
불법 복제품 쓰나???

아무튼... 지금 하려는게 Serial 통신으로 packet을 주고 받는 일이다.
PC의 입장에서 보면 RS-232로 연결된 디바이스에서 받을 수 있는 데이터의 종류는 두가지 종류이다...
한가지는 그냥 막 날라오는 정보...
다른 한가지는 PC의 요청에 의해 받아지는 정보...

Thread를 쓰지 않고 그냥 ReadFile 함수를 사용해서 직렬 포트를 내가 원하는 시점에 읽으면, 막 날라오는 데이터를 제때 읽지 못할것이고...
Thread를 써서 직렬 포트에 있는 데이터를 읽을 경우에는 PC에서 보낸 여러개의 요청을에 대한 response들이 올경우, 어떤식으로 구분해서 읽어야 할지 모르겠다.
전역변수를 사용해서 쉽게 할 수는 있을것 같지만 나는 전역변수를 증오한다...

어떻게 보면 쉬운 일일것 같은데 왜 이렇게 헤매고 있는지 모르겠다... 아무래도 MFC가 불편해서 그런것 같다. OVERLAP structure와 같은 개념도 이해가 잘 안가고... MSDN찾아가면서 해보고 있지만, 회사에서 주는 무언의 압력때문에 항상 쫓기는 기분에 집중도 잘 안된다...
아무튼... 나는 MFC를 싫어해 !!!

Posted by Dansoonie