Posts Tagged ‘Windows’

CCheckListbox and item height

Well, MFC shows its age.

Although many fairly new programmers, who started to write code after the year 2000, think MFC is old, but in 90’s it was not.
It’s not as elegant as Cocoa or even new .NET ( with C#. .NET for C++ looks like too much overloaded truck with redundant stuffs on it. ).
However, it solves problems for its generation, and there was good reason for MS people to take such design.

However, they had to renovate it. There are many issues like control vs. view for similar components, inconsistent way to deal with widgets, etc.
Today I found a problem with item height for CCheckListBox. With VS resource editor, you can change “font size” of a dialog box or a window. What it actually does is not to change font size for widgets on them.

font size( I think it’s also a problem. What it actually does is to change “scale” of the coordinate system on that dialog box or window. Because the scale is changed, everything like button size is also changed as well as font size. So, it’s not right to name the property “Font(Size)”. )

Problem is that when an instance of CCheckListbox is instantiated and items are added to that, it checks whether each item height is bigger than its minimum size like this. ( Please focus on the last line. )

void CCheckListBox::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
  // You must override DrawItem and MeasureItem for LBS_OWNERDRAWVARIABLE
  ASSERT((GetStyle() & (LBS_OWNERDRAWFIXED | LBS_HASSTRINGS)) ==
    (LBS_OWNERDRAWFIXED | LBS_HASSTRINGS));

  CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
  ENSURE(pDC);

  if (((LONG)(lpDrawItemStruct->itemID) >= 0) &&
    (lpDrawItemStruct->itemAction & (ODA_DRAWENTIRE | ODA_SELECT)))
  {
    int cyItem = GetItemHeight(lpDrawItemStruct->itemID);
    BOOL fDisabled = !IsWindowEnabled() || !IsEnabled(lpDrawItemStruct->itemID);

    COLORREF newTextColor = fDisabled ?
      RGB(0x80, 0x80, 0x80) : GetSysColor(COLOR_WINDOWTEXT);  // light gray
    COLORREF oldTextColor = pDC->SetTextColor(newTextColor);

    COLORREF newBkColor = GetSysColor(COLOR_WINDOW);
    COLORREF oldBkColor = pDC->SetBkColor(newBkColor);

    if (newTextColor == newBkColor)
      newTextColor = RGB(0xC0, 0xC0, 0xC0);   // dark gray

    if (!fDisabled && ((lpDrawItemStruct->itemState & ODS_SELECTED) != 0))
    {
      pDC->SetTextColor(GetSysColor(COLOR_HIGHLIGHTTEXT));
      pDC->SetBkColor(GetSysColor(COLOR_HIGHLIGHT));
    }

    if (m_cyText == 0)
      VERIFY(cyItem >= CalcMinimumItemHeight());

It turned out that cyItem, which is height of an interested item at that moment, is less than the minimum height if the font size is set to 12.
So, MFC is not updated to work with its visual resource editor or vice versa.
At least there should be some property to choose item height based on chosen “Font size” on the visual editor. If the code for MFC presents relevant error message when debugging, it can be even better.

Anyway, if you set the item height using SetItemHeight() sufficiently, its debugger will not complain again. This is not documented in the section for CCheckListBox at all.

We complain that Apple let Mac OS X and its Cocoa framework behind due to its focus on iOS. ( kernel is the same on the both and Cocoa is almost same to CocoaTouch, but still.. ) However, Apple people keep updating their tool set to work properly with their framework. MS doesn’t seem to be considerate on this long-lived-but-dependable MFC framework. Yes, model-wise, .NET is better. But I often notice that .NET with C++ is too bloated and .NET with C# is too weak. For native environment, MS doesn’t have new framework to replace MFC for C++.
Nowadays, it doesn’t seem to me that there are many S/W engineers working with MFC/C++. So, probably they don’t ask much to MS. Well, in the world of Web app, Java and C#, where people usually justify “computers are getting faster. So, bytecode/VM language like C#/Java are OK.”. I think it’s understandable argument. But still it’s not sufficient to me. It’s like to use 486 computers with the speed of 386 computers. For convenience of using and learning a language, MS gave up many things in C#/.NET, which can be done more easily with C++/MFC/Win32.

Windows Reflection vs. Parent handling of background color for Windows widgets ( MFC )

With MFC, to paint the background of a controls or widgets, you can override OnPaint(), but there is another mechanism in that the parent object of a control provides background color for the control.

That is to make the parent respond to WM_CTLCOLOR or one of its variants, but in MFC 4.0 ( which is already pretty old ) provides more expanded functionality of that. It’s called Message Reflection. With Message Reflection, interested messages can be handled by the child control windows as well as the parent windows.

TN062: Message Reflection for Windows Controls
NOTE : Ok. Here is another example I think the MFC engineering team did wrong.

When we say “Window”, it means “Window”. However, in Win32/MFC terminology, it can mean other controls/widgets.
For example, if you want to set a text of a CEdit, you call CEditInstance->SetWindowText().

It’s not to change the “title bar text” of the window. It’s to set text of the CEdit. Why is it designed as such?
Well, there are two different classes in MFC, i.e. CWindow and CWnd. CWindow is for “Window” which we know generally. CWnd is a parent class of any visual elements or Widgets in MFC space. However, as the class name implies, we, long time windows programmers, tended to mention that as a class for window.
So, there is nomenclature problem. There are many wrong doing in design of MFC. If compared to that of .NET or Cocoa, we can see how poorly MFC was designed.
I hope MS someday fixes all the problems of MFC, but I doubt if it would happen, because they nowadays concentrate more on C#/.NET ( not even C++/.NET )
Well.. CLR is practically fast. That’s what most people, especially S/W engineers working for “business logic” think. Yeah.. they were Visual Basic or Java programmers. To their standard, they think CLR is very fast. To people like me, who have been hardcore native C/C++ programmers and someone who has a background in Computer Science, we don’t think so. Well.. more strictly speaking, we know that it’s practically fast. Probably most C++ programmers in their 20’s and 30’s nowadays are kind of new kids on the block to me, and they will not agree with me. However, in 80′ and 90’s we had agreed upon that.

 

 

How much complete a framework can be : MS vs. Apple

As a person who major in CS, I have interest in fundamental technology or techniques like compilers, OS, 3D graphics, computer vision, parallel systems & distributed systems. So, one of the reason I started to work with 3 major OSes, i.e. Windows, Unix and Mac, and have had lots of interest in their architectural design. Therefore I like to work with different frameworks and compare their design or philosophy behind them.

I think OS architecture is like a whole picture, while frameworks are each part of the OSes. What architectural design an OS has is reflected to its frameworks. When overall architecture design affect how they work, how their components are related one another and so on, frameworks for them should be designed as such. This is one of the reason I think Apple should have filed with OS architectures than their visual UI design against MS and Google.

Here, I would like to show the very difference between .NET and Cocoa. If you have followed ToolBox API and Win32/MFC, you will see similarity between Apple’s and MS’s. Also, there are similarity between Cocoa and .NET. I think it is because Objective-C/Cocoa is in the SmallTalk camp which test OOP concept in academia and geared toward SE, while C++ is in Simula camp which is more for real industry field. Because C++ is for more real field, it should have been compromised with many restriction like CPU speed etc. Also the C++ has been evolved for everything for all people. So, although C++ was introduced as THE OOP language, it has many different concept like meta programming, ad-hoc polymorphism. Also, because of that it also contains its syntax which became somewhat bad and some concept got to have many semantics. (e.g. extern vs. static ) C# is not too different from C++ in that. Although MS streamlined C# from C++. (actually C# was influenced more by Java at first. But as its name suggests it has the face of C++. # in its name is somewhat amusing. When they call it, don’t forget that it is called “sharp” rather than “pound”. # in musical notation is half higher than a note it is attached too. So, C# is C++ in that sense. ) I can feel those philosophy to be all for all from C#.
However, Objective-C and Cocoa was evolved to be focused to increase productivity. So, when using Objective-C and Cocoa, you naturally become to focus on core logic rather than “how to achieve that”. Objective-C is more simple and Cocoa is designed to be very intuitive and powerful.

OK. Let’s see how Objective-C/Cocoa achieves “GUI code on main thread”.

- (IBAction)doInThread:(id)sender
{
    [NSThread detachNewThreadSelector:@selector(doSomethingMethod:)
                             toTarget:self withObject:nil];
}

// Thread method
- (void)doSomethingMethod:(id)object
{
    // Calls appendLogMessage: on main thread
    [self performSelector:@selector(appendLogMessage:)
                 onThread:[NSThread mainThread]
               withObject:@"Do something..."
            waitUntilDone:YES];
}

- (void)appendLogMessage:(NSString *)messageString
{
    NSTextStorage *textStorage = [m_logBoxView textStorage];
    NSUInteger theLastPos = [textStorage length];

    [m_logBoxView setSelectedRange:NSMakeRange( theLastPos, 0 )];

    [m_logBoxView insertText:[NSString stringWithFormat:@"%@\n",
                              messageString]];
}

It’s very intuitive. (Don’t confuse with that you don’t understand Obj-C code. Once you get used to it, it is very easy and straightforward. ) The appendLogMessage: is written just like a normal message/method.

Now, let’s check how it looks in C#/.NET.

#region MSDN way
private void m_doSomethingButton_Click(object sender,EventArgs e)
{
    m_choreThread = new Thread(new ThreadStart(this.StartThreadLoop));

    m_choreThread.Name = "MSDN Thread";
    m_choreThread.Start();
}

// Thread method
private void StartThreadLoop()
{
    // This is a thread loop
    int i = 0;

    while (i < 10)
    {
        // 1. Call WriteLogMessage()
        this.WriteLogMessage(String.Format("Do chores hard!!! {0} from {1}", i, m_choreThread.Name));

        i++;
    }

}

// 2. Visit this in the non-main thread space
// 5. Visit this in the main thread space
private void WriteLogMessage(string msgString)
{
    // 3. If it is still in the context of a non-main thread
    if (m_logTextBox.InvokeRequired)
    {
        WriteLogMessageCallback writeLogMessageDelegate = new WriteLogMessageCallback(WriteLogMessage);

        // 4. Invoke in its main thread space
        this.Invoke(writeLogMessageDelegate, new object[] { msgString });
    }
    else
    {
        // 6. Call this in the main thread space.
        m_logTextBox.AppendText(msgString + Environment.NewLine);
    }
}
#endregion

I commented how things are visited in the C#/.NET case to help your understanding. So, to you, who use the framework, .NET case prevent you from concentrating on the main logic. In other words, you should know how things work in C#/.NET.

One of the virtue of OOP is data hiding and encapsulation. Although it says “Data Hiding”, it’s not only about “Data” but also “how it works internally.” C#/.NET fails in this area seriously as you can see. In other words, you should be aware of in which thread context the WriteLogMessage() is called and the method should be implemented with that knowledge.
Compared to that, messages in Objective-C/Cocoa can be written just like usual messages.

Then, are they really different? Couldn’t MS make their .NET framework as elegant as Cocoa? No. I don’t think so. It looks to me that Cocoa’s underlying code could be similar to that of .NET. The difference is that how much Apple people refined their framework by considering people who actually use their framework and design the framework to let people to focus on their own logic not on how Apple implemented this and that.

Then, let’s try to make it look similar to that of Objective-C/Cocoa.

#region Cocoa Way
private void m_doSomethinginCocoaWayButton_Click(object sender, EventArgs e)
{
    WriteLogMessage2(Environment.NewLine + "----------------------------" + Environment.NewLine);
    m_choreThread = new Thread(new ThreadStart(this.StartThreadLoop2));
    m_choreThread.Name = "Cocoa Thread";
    m_choreThread.Start();
}

private void StartThreadLoop2()
{
    // This is a thread loop
    int i = 0;

    WriteLogMessageCallback writeLogMessageDelegate = new WriteLogMessageCallback(WriteLogMessage2);

    while (i < 10)
    {
        this.performOnMainThread(writeLogMessageDelegate,
                                 new object[] { String.Format("Do chores hard!!! {0} from {1}", i, m_choreThread.Name) } );

        i++;
    }

}

private void performOnMainThread( WriteLogMessageCallback methodToInvoke, object[] parameter )
{
    if (m_logTextBox.InvokeRequired)
    {
        this.Invoke(methodToInvoke, parameter);
    }
}

private void WriteLogMessage2(string msgString)
{
    m_logTextBox.AppendText(msgString + Environment.NewLine);

}
#endregion

Don’t bother with the method name “performOnMainThread“. It’s not our interest. Whatever the name is, it doesn’t matter. What we need to focus on here is the pattern of how WriteLogMessage2() is called.
Also, additionally assume that Object class in .NET framework, which all classes are inherited from, contains the performOnMainThread(). Then like Cocoa, you can ask an object to invoke a given method on main thread. Then you, as a application program developer, can write the method to be invoked without worrying about knowing how those invoke system works.

Similar things happens with timer invocation. If you want to invoke a message at certain intervals in Cocoa, the code is very straightforward and very clean. However, in Win32/MFC case, the OnTimer() handler should check what timer triggers this timer event. In this case, it looks to me that Apple people utilizes signals and events. (Signal is so-called H/W events while event is called S/W event, if you want to be specific about the terms. ) I will not show sample code for that here.

Point here is that the level of refinement is higher on Apple’s. Cocoa framework is designed for SE more in mind, while MFC/.NET are more about “Let’s put this on the market as quickly as possible.” Good news is that.NET is more similar to Cocoa than their previous frameworks, because NeXT showed a future a while ago and MS looked to adopted that.

I always wonder why MS simply adopted Objective-C/Cocoa for their platform development. Well, C#.NET was a kind of a gun toward Java and MS languages can share the same .NET framework. So, there is slight difference, but even with Objective-C/Cocoa, there is a language bind. Well.. it’s true that people should make their own Cocoa equivalent.. yeah.. that can be the major issue to MS.
( Well.. I know that not choosing Obj-C/Cocoa or OpenStep by MS was also due to market situation, marketing, etc, but here I would like to focus on technical side. )

I wonder how F-Script people and Ruby Cocoa people bridged their language to Cocoa. (Script Bridging tech.. )

오늘 발표된 Windows 8 RT

타이밍이 묘하다.
불과 며칠전 Windows 8에 대해서 포스팅을 했다. 그때의 느낌을 정리하자면 데스크탑 OS라고 하기엔 태블렛 OS이고 태블렛 OS라고 하기엔 데스크탑 OS라는 점이다. 이것이 현재의 Notebook과 tablet들에 장착이 되면, 이도 저도 아닌 OS가 된다는 점이었다.

그런 OS를 사용할 MS의 새로운 태블렛이 오늘 나왔다.

이 디자인은 ASUS의 Transformer와 완전 동일하다. 단지 키보드 부분을 마치 Apple의 Smart Cover 느낌이 나게 만들었다는 것일 뿐.

그런데, ASUS의 그것을 볼때완 사뭇 다른 느낌이다. Steve Jobs가 iOS를 그리고 iPhone을 발표하면서 쓴 방식은, 조삼모사(朝三暮四)의 방식이었다. 만약 Native 개발 환경(framework, 언어)를 HTML/AJAX보다 먼저 발표했다면, 그다지 관심을 끌지 못했을것이다. “한정된 시장용 언어와 프레임워크를 배워 뭐해”라는 것이 그당시 기본 분위기였기 때문이다. (물론 Apple을 좋아하는 사람들은 그래도 하겠지만 전반적인 분위기와 Apple것을 좋아해도 시장 전체를 보는 사람들의 의견은 그랬다) 하지만 그때 분위기는 HTML/AJAX였고, 그런 상황에서 이미 많은 웹 프로그래머들은 곧장 iPhone 프로그래머가 될 수있다는 것은 대단한 매력이었다. 그리고나서 iPhone을 접하고 나니, 네이티브 개발에 대해서 관심을 가지게 된 것이다.
똑같은 것인데, 표현을 달리했을때, 순서를 바꿨을때, 디자인을 바꾸었을때, 사람들에게 주는 느낌이 확연히 달라지는 경우가 있다. Steve Jobs는 이것을 잘했다. 아주 적절한 타이밍에 적절한 디자인으로 “뭔가 다르다”, “뭔가 있다”라는 느낌을 주는데 탁월한 재주가 있었던 것이다.

그런데 오늘, 이 Windows 8 타블렛에서 그런 것을 느낀다. ASUS것과 분명히 같은 모양인데도, ASUS의 것은 그저 그런 조악한 개념의, 태블렛에 불편한 텍스트 입력을 키보드 악세사리로  해결한다.. 딱 그 정도의 느낌이었다.
하지만 이 Windows 8에 저렇게 되었을때는 사뭇 다른 느낌을 불러 일으킨다.
Windows 8을 사용해 보고 있는 느낌은, 앞에서 정리한 대로다. 이도 저도 아닌 OS지만, 상황에 따라 이것도 저것도 다할 수있는 팔방 미인으로 인식될 수도 있다. 전자의 느낌을 후자로 전이시키게 만드는 것이, 마케팅의 힘과 기술적 가능성을 보여주는 능력이라고 본다. iPad를 쓰다보면 느끼는 것이, 때때로 이게 노트북이었으면 할때가 있다. 반대로 노트북을 쓰다보면 이게 타블렛이면 좋겠다 싶을 때가 있다. MS가 이 부분을 마케팅과 기술에서 ( 제공하는 애플리케이션, Use Case를 잘 보여준다면) 잘 두드러지게 할 수있다면, 상당한 성공작이 될 것 같다.

물론 장사에서 성공하느냐는 별개의 문제다. 기술적으로 성공해도 시장에서 선점을 당해 성공 못하는 경우는 이미 우리는 익히 알고 있다. 그러므로 이것이 시장에서 성공할지는 명확하지 않다. 스티브 발머가 잡스처럼 사람들을 매혹시키는 능력이 있다면, 그리고 설득력있는 프로그램들과 사용행태를 보여준다면 분명 가능하리라고 본다. 하지만 이미 그런 부분을 더 잘하고 있는 Apple의 iPad/iPhone과 싸다는 측면과 가짜 오픈소스로 오픈소스인양 하는 안드로이드가 사람들의 마인드 쉐어를 꽉 잡고 있는 이 시점에, 과연 얼마나 효과적으로 이 Windows 8 태블렛을 소비자들에게 어필시킬 수있을지 궁금하다.

하지만 기술적으론 해볼만하다고 생각한다.

사실 이 RT 버젼 말고 Windows 8 Pro 태블렛도 있다. 하지만 이것의 가격은 UltraBook의 그것에 비견된다고 하니, 시장 차별성에서 효과적일지 모르겠다.

(이미 UltraBook은 심각한 문제가 걸려있다. 사람들이 Windows를 선택하는 이유중의 하나가 저렴하다는 것이다. 하지만 Dell이나 HP의 홈페이지에 가서 스펙과 가격을 MacBook Air등과 비교해 보라. 아마 더 비싸다는 것에 깜짝 놀랄 것이다. 예전에도 물론 애플 옹호론자들이 그런 비교를 종종 하곤 했다. 하지만 그때와 지금은 큰 차이점이 있다. 그때는 Windows 하드웨어의 사양을 Mac처럼 SCSI도 붙이고 뭐도 붙이고 해서 비교를 한것이다. 하지만 대부분의 윈도우즈 사용자들에게 그런 것들은 필요하지 않아서, 실제 별 실효성이 없는 비교였다. 하지만 지금의 것은 다르다. 거의 barebone 의 기본적으로 꼭 필요한 것들만 있는 사양에서 그런 차이가 난다는 것이다. 아마도 애플이 부품을 선점해서 그런게 아닐까 하는데..  )

하지만 소프트웨어쪽에서는 해 볼만 하다고 본다.

물론 어떤 사람들은 ARM 코어를 쓰는 저 RT는 기존이 Intel용 프로그램을 못 돌린다는 소리를 한다. 하지만 이는 얼마든지 극복이 가능하고, 이미 MS는 극복할 수있는 여러 방법이 있다. 아직 이해를 잘 못하실 분들을 위해서 이 부분을 열거해 보자.

  1. Windows 8에서는 AJAX 기반의 프로그래밍이 새로 추가 되었다. 이 부분은 native code가 관여하지 않는다. 어떤 플랫폼에서든 돈다. 이런 개발 방식이 .NET, MFC/Win32와 같은 그런 관점의 개발 환경으로 추천된다. (이것은 .NET 개발자들에게 큰 원성과 우려를 낫기도 했다. ) Win8용으로 이 방식을 이용해서 만들면 어떤 CPU 아키텍쳐에서도 돈다.
  2. CLR 기반의 C#, C++ .NET은 native code 보다는 intermediate code를 생성한다. 즉 하부 하드웨어 구조가 달라도 돌아갈 수있는 코드가 만들어진다. (100% 그런 것은 아니다. 여러분의 프로젝트가 native code로 되어 있는 라이브러리를 링크할때, 네이티브 코드도 포함할 수있다. ) 그러므로 Intel 프로세서를 위해 컴파일 된 것이, 컴파일 되어 봤자 x86/64 코드가 아니라 그런 바이트 코드(Intermediate code)로 나오기에 하드웨어 종속성을 갖지 않는다. 9물론 충분히 완벽하게 가다듬을지 아닐지는 아직 시간이 더 필요할거다. 물론 현재로써 byte code는 호환성이 있지만, 좀더 세밀한 부분에서 조정이 필요한 점도 분명있을 것이다. 하지만 기본적으로 같은 Windows기 때문에 executable file format도 같을 것이기 때문에, 큰 문제가 없을것이라고 본다) 정리해보자면 순수 managed code로 만든다면 하부 아키텍쳐가 ARM이던 Intel이던 상관없다. (이론적으로. 자바도 이론적으론 한 플랫폼에서 컴파일하면 다 돌아간다 하지만, Sun에서 컴파일한 것을 Windows로 가져왔을때, 클래스 못찾는 경우- 클래스 패스를 제대로 정했음에도-를 많이들 보았을 것이다. 이럴 경우 소스코드 변경없이 다시 해당 플랫폼에서 컴파일만하면 된다. 아마도 심볼테이블이나 뭔가가 좀 달라서 이런 문제가 생길 것이라고 생각된다. )
  3. 소스 코드 레벨의 호환성 : 바이너리 레벨에서 달라도 소스코드가 같다면 컴파일 타겟만 달리하게 되면 되기 때문에 개발자들에게 문제가 없다. 같은 언어, 같은 프레임워크를 사용한다면 소스 코드 레벨에서 호환성이 부여된다.
  4. multi-binary format : Apple이 PowerPC와 Intel 칩용으로 했듯이 여러 아키텍쳐용 코드를 한 바이너리가 포함할 수도 있다. 이것은 Windows에선 아직 구현이 안되었지만 (구현할 필요도 없다고 본다), 여기서 언급하는 이유는 기술적으로 가능하기 때문이다.
  5. Emulation (요샌 가상 머신이란 말을 더 많이 쓰긴 한다만) : 잊지말자 Virtual PC. 기억들 하시는지? 90년대에 맥용으로 있었던 맥에서 Intel PC들을 에뮬레이션하는 소프트웨어였다. 그 회사를 MS가 흡수 합병했다. 그 후로 Parallels니, VMWare니, Virtual Box같은게 나왔다. 즉 MS가 기술적으로 못할 이유가 하나도 없다.

이쯤되면 마케팅 기술과 대중 선동기술이 필요한 시점이다. MS의 마케팅 기술은, 싼값에, 시장 선점을 한 것을 무기로 하는 것이었지, 이미 선점당한 시장에서 기술적 매력과 대중 선동 기술로 하는 것이 아니었다. 그러므로 과연 이 “가능성 있어 보이는” 것이 성공할지는 지켜 보아야겠다. 1984년과 달리 이제 MS에는 Apple외에도, windows의 성공 모델을 꼭 빼다 닮은 Android 진영이 있다. 즉 대중 선동력이 있는 Apple이라는 적과, 자기랑 꼭 빼닮은 Google 연합군과 싸워야 한다. 이 두 상대를 향해 빼들어야 할 칼은 분명이 다른 모습이어야 할거다. 이 두 칼을 MS가 과연 찾아낼까?

Windows 8 : Tablet OS와 Desktop OS의 결합

오늘 Windows 8 Trial을 다운로드 받아, VirtualBox라는 가상 머신 프로그램을 설치하고, 그 안에 설치했다.
설치 과정은 무척이나 빨랐고, 깔끔하였다.

Windows 8은 기본적으로 기존의 데스크탑을 보여주지 않는다. 메인 화면은 큰 사각형의 버튼으로 된 “메트로 UI”로 된 바둑판 메뉴를 제공한다.

우선 어떤 느낌인지 보기 위해, Bing 지도 프로그램을 클릭해 보았다.

화면을 가득 채우는 아름답게 디자인된 Bing 지도 앱이다. 상당히 기능적이고, 반응성도 빠르다.

MS가 상당히 공을 들였다는 것을 알 수있다.

그런데 문제가 슬슬 보이기 시작했다. 이게 타블렛이면 상당히 좋겠는데, 마우스를 쓰는 데스크탑에선  불편하다. 우선 예전과 달리 Quit 버튼이 없어, 어리 둥절하다. 만약 이게 타블렛이었으면 어땠을까? 화면에 보이는 버튼들 중에 없으며, 태블렛의 본체에 있는 버튼을 누르게 딜것이다. 마치 iPhone의 Home 버튼처럼. 그래서 문제가 없는데, 키보드를 쓸때는 도대체 어떤 버튼을 눌러야 할지 알수가 없다. 혹 화면 어딘가에 버튼이 숨어있지 않을까? 특정 키 조합이나 제스쳐를 취하면 메인 메뉴 화면으로 가지 않을까, 혹은 숨겨진 메뉴가 나오지 않을까 생각했다.

어떻게 메인 화면으로 돌아갔을가? 바로 Windows 키이다.

화면 전환은 무척 빨랐다. 하지만 글쎄다. 노트북이나 데스크탑에서 Windows 키를 누르는 것을 사람들이 직관적으로 생각해 낼까?
노트북은 날지도 모른다. 대개 트랙패드가 있고, 요샌 멀티터치가 되니, 어떤 제스쳐가 있을 것 같아 보이기 때문이다. 하지만 데스크탑은.. 대개 전통적인 마우스를 가지고 있을텐데..

자.. 다음은 날씨 프로그램이다.

화면을 꽉 채우는, 시각화가 인상적인 날씨 프로그램.

태블렛을 가지고 있다면, 밥할 때, 식탁 옆등에 놓으면 좋겠다는 생각이다. 일종의 사진액자처럼 쓸 수도 있겠고. 하지만.. 멋있는 화면의 이면에, “이게 과연 이렇게까지 할 필요가 있나?” 싶다.

다음은 제일 처음에 보일, Metro UI의 메인 메뉴화면이다.

이것이 Windows 8 장비에 로그인을 하면, 처음 맞이할 Metro UI로 된 메인 메뉴 화면이다. Zune을 보신 분들은 금방 눈치 채실 것이다. 바로 그 UI를 그대로 가지고 왔다.

Zune에서 좀 독특한 텍스트 기반의 UI를 소개했다. MS 는 이것을 상당히 좋게 생각하는 사람들이 많은지, 이걸 계속 민다. 내 개인적으론 정신이 산란하고, 특히 원색의 사각형들이 많아, 눈이 무척 피곤하고, 정신 집중을 방해하는 경향이 있다.

데스크탑 월페이퍼를 놓고 보더라도, 애플은 미색을 사용해서, 정신 산란하지 않게 하고 눈에 부드럽게 한다. 그리고 문서를 띄었을때 바탕 화면보다는 작업하는 문서에 집중을 할 수있도록 해 놓았다. 하지만 MS 는 애플과 마치 멋있는 데스크탑 월페이퍼 경쟁하듯이, 너무나 선명하고 또렷한, 그리고 원색적인 사진을 주로 가져다 놓았다. 개인적으로 그래서 Windows에서는 꼭 웹을 뒤져 다른 사진을 찾아 넣는다. Mac에선 그냥 애플이 주는 것을 쓰는데.
즉 MS는 내가 보기엔, 아직도 왜 Apple이 저렇게 디자인을 하는가에 대한 이해가 없는 것 같다.

또 하나의 문제. 프로그램이 많으면, 좌우로 스와이핑해서 혹은 하단의 스크롤바를 이용해서 쭉쭉 더 많은 프로그램을 볼 수가 있는데, 여러 프로그램을 설치해서 쓰는 사람들은 많이 스크롤을 해야할지도 모른다. 모바일 장비에서 이런 디자인을 하는 것은 이해가 된다. 화면이 작으니, PC처럼 파일 이름등을 표시하면 (Windows CE혹은 Windows Mobile등을 사용해 봤다면 무슨 말인지 알것이다. 그 OS들은  심지어 C:\windows 디렉토리까지 그대로 노출한다. 글자가 너무 작아 뭐 하기도 힘들다) 사용하기가 힘들기에 큰 아이콘에 그림/사진을 위주로 배치하는 것이 유용하다. 하지만 이것은 desktop OS다. 사람들은 키보드와 마우스를 쓸 수있다. 키오스크용으론 적당할지 모르겠으나, 일반적으로 작업하기 위한 UI로써는 나쁜 디자인이라고 생각한다.

자.. 여기서 좌측 하단의 Desktop을 주목하자. 저걸 누르면 Windows 8에서 기존의 데스크탑을 볼 수가 있다.

기존의 데스크탑과 거의 같다. 하지만 웬지 어색한 느낌도 든다.

비록 기존의 프로그램들이 이 화면에서 돌아가고 쓸 수가 있지만, MS는 Metro 스타일로 만들기를 권장한다.
이 화면에서 메인 메뉴로 나가려면 역시 windows 키를 누르면 된다. 그런데 다른 방법은?
예전에 시작 버튼이 있던 좌측 하단 (IE 아이콘 좌측 옆)에서 아래의 방향으로 마우스를 움직이면 다음과 같은 메인 메뉴화면의 축소된 그림이 나온다. 그걸 누르면 메인 메뉴로 빠져 나간다.

좌측 하단의 메인 메뉴 화면 미니어처 이미지가 나타난다.

VirtualBox에서도 굉장히 빠르게 동작하는 등, 잘 만들었다. Windows 8. 하지만 이런 생각이 든다. 메트로 메뉴 화면과 기존 데스크탑 화면이 뭔가.. 마음에 맞지 않는 두 사람이 결혼한 느낌? 아니면 예전의 Bob과 같은 느낌이다. 애플에도 있었지? CyberDog이라고.. (CyberDog은 OpenDoc 기반 모듈형 웹 브라우져였다. Bob이 개 그림이어서 순간.. 섞였다. ) 무슨 말인고 하면, 굳이 쓸 필요가 없는데, 거기에 해당 프로그램에 접근할 수가 있는 링크가 있어서 들어가야 하는 또 하나의 “데스크탑”을 만든 느낌? MS가 이해한 타블렛 OS와 Desktop OS의 통합이란 느낌이다.

애플의 방식도 어찌 보면 비슷하다. Launch Pad.. 근데. “발사판”은 독립 프로그램으로 되어 있어서, 그다지 이상한 느낌은 안드는데, 즉 두개의 다른 환경이 같은 OS에 있다는 느낌은 안드는데, Windows 8은 그런 느낌이 있다.

이 환경은 이상하게 기존 Windows와의 단절이 되는 느낌이다. 분명히 OS는 두 환경을 다 가지고 있는데.. 통합이 아니라 단절이 느껴진다.
그리고 Metro는 파일의 개념이 없다는 것이 (유저입장에서) 특징이다. Jeff Raskin의 매킨토시가 또 다시 한번 세상을 휩쓰는가?

내 생각에.. 내가 맥도 쓰는 사람이 아니라면.. 어차피 Windows 8에서도 HTML5/JavaScript 프로그램을 권장하니 (여전히 .NET프로그램과 MFC/Win32도 지원하지만), 차라리 Chrome OS같은 단일 환경으로 넘어가고 말겠다. Chrome OS는 이런 이질감은 안들던데.. Win8은 이상한 이질감이 든다.

여러분은 어떤 생각이 드시는지?

How not to build with “ClickOnce” deployment option?

“ClickOnce” deployment is cleaner and easier option than “InstallShield” option. Also, it is free.
However, there is one glitch. ( MS people will call it a “feature”. )
“ClickOnce” doesn’t allow execution level higher than “AsInvoker”. So, it means that you can’t include a call to some functionality which requires “Administrator” privilege.
What? Isn’t it totally different thing to elevate execution level when launching, and building/deploying an executable? Right. However, it’s the approach MS people chose, and when building a project, it will warn and stop building.
In my code ( I got rid of “s” here, because my native English speakers said it was wrong if you wrote/speak codes. Well, a language keeps changing. According to English grammar book, you should not say, “Give me (a) milk”. A correct one will be “Give me a cup of blah blah”. But one very surprising thing I found in living here is that there has been virtually no person who ordered like “give me one cup of Cafe Mocha”, “Give me one glass of Coke” etc. They always say “Two Cokes”, etc ) I call WMI method to enable/disable network interface. It requires “Administrator” privilege.

So, I had to change a deployment method not to use ClickOnce.

However, how not to use ClickOnce? Isn’t it enough not to click “Publish” menu item?
Visual Studio still spit out the error message.

How to solve it is to turn off “Security Option” like shown below.

How to turn-off checking “ClickOnce” in building

 

The following is when the option is on.

ClickOnce doesn’t support “Administrator” level

 

 

Enabling and Disabling Network Interface on Windows using C#

It doesn’t need to be C#. The main thing here are :

  • WMI (Windows Management Interface)
  • Administrator Privilege

Once you get a reference to the WMI object, you can invoke its Enable() and Disable() method.

Let’s make things short. Here is example code.

static void DisableAndEnableNetworkAdapter(string nicName)
{
	ManagementClass managementClass = new ManagementClass("Win32_NetworkAdapter");
	ManagementObjectCollection mgmtObjectColl = managementClass.GetInstances();

	ManagementObject myObject = null;

	foreach (ManagementObject mgmtObject in mgmtObjectColl)
	{
		if (mgmtObject["NetConnectionID"] != null && mgmtObject["NetConnectionID"].Equals(nicName))
		{
			Console.WriteLine("found");
			myObject = mgmtObject;

			//object result = mgmtObject.InvokeMethod("Disable", new object[] {});
			//
			// When there is no parameter, you don't need to pass an object array with
			// no element in it.
			object result = mgmtObject.InvokeMethod("Disable", null);
			Console.WriteLine("{0}", Convert.ToInt16(result));
		}
		//Console.WriteLine("{0}, {1}", mgmtObject["Name"], mgmtObject["NetConnectionID"]);

	}

	object result3 = myObject.InvokeMethod("Enable", null);

}

(This code is written to be invoked from Main() method. So, it is declared as “static”. )
However, if you invoke this one in a Main() method, it will not change the activated status of a network interface. The reason is the executable doesn’t have “admin” privilege.

So, try to create you own app.manifest file and change the privilege like this.

<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />

If you want to know more about “requestedExecutionLevel”, please cf. Step 6: Create and Embed an Application Manifest (UAC)

If you want to do experiment with netsh, cf. How to disable Local Area Connection using Command Prompt in Windows 7?

In Channel 9 page of MS, it is said that they hosted “ToggleNic” sample project for this, but it is not possible to find it there. However, I found it somewhere else. The ToggleNic code contains one interesting thing. For “Disable”, the author passed new object[] {} as its 2nd parameter. However, for “Enable”, he just passed null. I was curious if passing an object array with nothing makes things different, but it didn’t. Why it was possible to enable/disable with ToggleNic was that it has its own app.manifest which is to obtain admin privilege. So, after I endow the same privilege to my project, it started to be able to enable and disable NIC including WIFI interface.

How to keep the reference to a delegate registered to a native API function

When you call a Win32 native function from C# using P/Invoke, there are times when the Win32 function requires a callback for various purpose like callback for status feedback.

Then, the callback functions are expected to be called repeatedly until it is unregistered.
However, the garbage collector frees up the callback function. ( It’s a delegate. )

Then how to prevent it from being collected?

Here is a nice blog post about it.
beefycode : Delegates and Native API Callbacks – Answer

In short, it is to declare a member variable to the delegate to make the subordinating class keep the reference to it.

MS doesn’t have philosophy in designing their framework

I would like to show very simple example.

These GetHeight() methods are declared in Font ( .NET )

GetHeight() Returns the line spacing, in pixels, of this font.
GetHeight(Graphics) Returns the line spacing, in the current unit of a specified Graphics, of this font.
GetHeight(Single) Returns the height, in pixels, of this Font when drawn to a device with the specified vertical resolution.

Method names and variable names should speak for themselves except for very special case where they lack of any nomenclature.

However, look at that. They are all GetHeight. However, what they return are different.
The first two return line spacing, while the last one is the height of a chosen font.
Because it is “GetHeight” of Font class, it should be the height of a font. That is self-explanatory for the method. So, the first twos are named wrongly. They should be “GetLineSapce()”. Also, because Windows now supports DPI-independency, the “GetHeight(Single)” should return a value in DPI independent unit. Moreover they should provide functions to convert the DPI independent size to device specific size, and vice versa. (ADDED : There is a way to do that currently. However, .NET is higher-level framework than MFC. Current approach looks more for Win32/MFC than .NET )

This shows that they don’t think about “what framework should address”. You can say that they didn’t have enough time for handling DPI-independence, but then they should not say DPI-independency in Windows 7 yet, just like Apple does for its Mac OS X.
More fundamentally, again, the method names are wrong.

How to Open Wireless Network Manager window on Windows 7

As we know, MSDN documentation is not good.
When I tried to figure out what format ShellExecute() needs for “open” command, this page didn’t explain even one bit about it.

So, by digging more, I could find this document, but it is hard to figure out what “window” (e.g. for Wireless Network Manager ) it is talking about, because I usually remember things by look not by words.

So, I would like to provide screenshots for them.

Connect to a network wizard”
lpFile : L”shell:::{21EC2020-3AEA-1069-A2DD-08002B30309D}\\::{38a98528-6cbf-4ca9-8dc0-b1e1d10f7b1b}”

Connect to a Network Wizard

Manage Wireless Networks Control Panel item”
lpFile : L”shell:::{26EE0668-A00A-44D7-9371-BEB064C98683}\\3\\::{1fa9085f-25a2-489b-85d4-86326eedcd87}”

They need to know how to write technical document like Apple.