Archive for the ‘Win32’ Category

Font rendering : GDI vs. DirectWrite from Mozilla

This blog post shows the difference of GDI vs. DirectWrite font rendering visually.
Great to read…

Emoji support on Windows

Unlike Mac, emoji support on Windows is not a feature which you can get easily. You have to write special code, etc. Also, depending on what API set your projects use, it can be supported or not.

So, here I’d like to summarize emoji support status of quo on Windows.

Script and Font Support in Windows

  • Win 7 : Segoe UI Symbol font was added to support many ( not all ) symbols encoded in Unicode. ( supports very limited set of emoji)
  • Win 8 : Segoe UI Symbols was updated in Win 8 to support completely ( but in B/W only. And I also personally saw that some emoticons are not displayed.)
  • Win 8.1 : Segoe UI Emoji font is added. Color font support.

 What’s new in DirectWrite in Windows 8.1

  • Starting in Windows 8.1, DirectWrite supports color fonts.
  • Direct2D uses DirectWrite with added enum value D2D1_DRAW_TEXT_OPTIONS_ENABLE_COLOR_FONT

What’s new in DirectWite in Window 8

  • supports the use of emoji in apps. (B/W) Previous versions of DirectWrite, presented with a missing glyph box if you tried to render an emoji ideograph. Starting with Windows 8, DirectWrite supports the Unicode codeblock associated with emoji, so if your app uses the Unicode standard codepoints for emoji it displays the appropriate glyphs.

Why on Windows the support of color emoji is not so drop-in is probably, MS approached color emoji differently than Apple & Google. Apple & Google’s approach is to make a font to point to a bitmap images in PNG, etc. However, MS approach is to introduce ‘layer’ to the font itself put the information directly.

Win32 Listview doesn’t look to support color emoji. Others in .NET space and WPF may support it. ( WPF is.. deprecated.. I’m sorry about people’s effort at one of my previous companies to switch to WPF and Silverlight. )

Text Rendering : GDI, GDI+, etc

Why text appears different when drawn with GDIPlus versus GDI

The wonders of text rendering and GDI

Unexpected behavior of Win32 when checking serial ports.

I recently noticed very interesting behavior in ClearCommError() function of Win32.
This code returns how many bytes there are in incoming buffer for a serial port.

DWORD CSerialPort::BytesWaiting()
{
  //Validate our parameters
  ASSERT(IsOpen());

  //Check to see how many characters are unread
  COMSTAT stat;
  GetStatus(stat);
  return stat.cbInQue;
}

void CSerialPort::GetStatus(COMSTAT& stat)
{
  //Validate our parameters
  ASSERT(IsOpen());

  DWORD dwErrors;
  if (!ClearCommError(m_hComm, &dwErrors, &stat))
  {
    DWORD dwLastError = GetLastError();
    TRACE(_T("CSerialPort::GetStatus, Failed in call to ClearCommError, Error:%d\n"), dwLastError);
    ThrowSerialException(dwLastError);
  }
}

However, after actually debugging it I found out that there are cases where

  • The number of bytes in its incoming buffer doesn’t increase while it is calling BytesWaiting() to see if it received enough bytes to read. Then, it should read its incoming buffer for the given COM port to have BytesWaiting() starts to return accumulated number of bytes after reading.
  • When BytesWaiting() returns 0, you still need to read the buffer not to fail in detecting any further data arrived from the other side of communication. reading 0 bytes in this case, will cause the BytesWaiting() keeps returning the number of bytes read after that point.

Normally, whether you read or not, callying BytesWaiting() correctly reports the number of bytes in an incoming buffer.
However, if any of those listed above happens, it stops reporting correct number of bytes.

So, this code fails.

int CLensControllerDlg::ReadIncomingPacket(BYTE incomingBuffer[], int numOfBytesToRead, bool *pShouldGiveUp)
{
     DWORD bytesInReceptionQueue;
     int readNumOfBytes, extraReadNumOfBytes;

     readNumOfBytes = extraReadNumOfBytes = 0;

     // First read
     readNumOfBytes = m_pSerialPort->Read( incomingBuffer, numOfBytesToRead );
     int lengthToReadFurther;
     int secondTryReadLength = 0;

     static int trialCount = 0;

     // Check if it needs to read once more
     if( (incomingBuffer[ 0] == (BYTE) 0x50) &&
           (incomingBuffer[ 1] == (BYTE) 0xAF ))
     {
           lengthToReadFurther = static_cast<int >(incomingBuffer[4]) + 1; // payload length + check sum
            // Read length + 1 more ( 1 is for checksum )

            //!!!!! [1] !!!!!
            // There are cases where bytesInReceptionQueue doesn't have accumulated number of
            // bytes in a reception bufffer.
            while( (bytesInReceptionQueue = m_pSerialPort->BytesWaiting()) < lengthToReadFurther )
           {
                Sleep( 3 ); // 10 msec
                trialCount++;

                //!!!!! [2] !!!!!
                // So, if the bytesInReceptionQueue doesn't contain the accumulated number of bytes
                // through the iteration, try to read some.
                // Then it will start to work again.
                 if( trialCount > 10 )
                {
                      if( bytesInReceptionQueue > 0 )
                     {
                            // Give another chance
                           secondTryReadLength = m_pSerialPort->Read( &incomingBuffer[readNumOfBytes], bytesInReceptionQueue );
                           readNumOfBytes += secondTryReadLength;

                           lengthToReadFurther -= secondTryReadLength;

                           trialCount = 0;

                     }
                      else
                     {
                            // let's see what it happens if try reading for 0 bytes and read further
                           BYTE temp[ 16];
                            int tempReadLength;

                            // bytesInReceptionQueue == 0
                           tempReadLength = m_pSerialPort->Read( &incomingBuffer[readNumOfBytes], bytesInReceptionQueue );
                           readNumOfBytes += tempReadLength;
                           lengthToReadFurther -= tempReadLength;

                            //// Once read, somehow, bytesInReceptionQueue starts to be accumulated again.
                            //bytesInReceptionQueue = m_pSerialPort->BytesWaiting();

                            //tempReadLength = m_pSerialPort->Read( &incomingBuffer[readNumOfBytes], bytesInReceptionQueue );
                            //readNumOfBytes += tempReadLength;
                            //lengthToReadFurther -= tempReadLength;

                           CString msgString;
                           msgString.Format( _T( ">> Will give up this incoming data : %x %x %x %x %x\r\n"),
                                                  incomingBuffer[0], incomingBuffer[1 ],
                                                  incomingBuffer[2], incomingBuffer[3 ],
                                                  incomingBuffer[4] );

                           WriteLogMessage( msgString );
                           TRACE( msgString );

                            if( pShouldGiveUp != NULL )
                           {
                                *pShouldGiveUp = true;
                           }

                           trialCount = 0;
                            return 0;
                     }
                }
           }

            // In the queue, now there are lengthToReadFurther or more to read.
           extraReadNumOfBytes = m_pSerialPort->Read( &incomingBuffer[readNumOfBytes], lengthToReadFurther );
     }

     return (readNumOfBytes + extraReadNumOfBytes);
}

The code above was written while I was debugging. So, it’s not clean nor compact.
So, here is better version if you want to see.

int CLensControllerDlg::ReadIncomingPacket(BYTE incomingBuffer[], int numOfBytesToRead, bool *pShouldGiveUp)
{
     DWORD bytesInReceptionQueue;
     int readNumOfBytes, extraReadNumOfBytes;

     readNumOfBytes = extraReadNumOfBytes = 0;

     // First read
     readNumOfBytes = m_pSerialPort->Read( incomingBuffer, numOfBytesToRead );
     int lengthToReadFurther;
     int secondTryReadNumOfBytes = 0;

     // Check if it needs to read once more
     if( (incomingBuffer[0] == (BYTE)0x50) &&
          (incomingBuffer[1] == (BYTE)0xAF ))
     {
          lengthToReadFurther = static_cast<int>(incomingBuffer[4]) + 1; // payload length + check sum
          // Read length + 1 more ( 1 is for checksum )
          while( lengthToReadFurther > 0 )
          {
               Sleep( 1 ); // 10 msec

               bytesInReceptionQueue = m_pSerialPort->BytesWaiting();

               // If it's normal, just waiting until bytesInReceptionQueue >= lengthToReadFurther,
               // and read the whole "lengthToReadFurther" amount of data all at once.
               //
               // However, sometimes the inbound buffer should be read to have further data accumulated.
               // If not,
               secondTryReadNumOfBytes = m_pSerialPort->Read( &incomingBuffer[readNumOfBytes], lengthToReadFurther );
               readNumOfBytes += secondTryReadNumOfBytes;

               lengthToReadFurther -= secondTryReadNumOfBytes;
          }
     }

     return readNumOfBytes;
}

LCD screen brightness control for MacBook with Intel GMA X3100 chipset

In my previous post, The Strange DeviceIoControl result with IOCTL_VIDEO_QUERY_DISPLAY_BRIGHTNESS, I said that query LCD screen as described in MSDN document didn’t work. Today I found out the reason. To tell the truth, I use a MacBook 13″ White with Intel GMA 950 chipset for the graphics component. So, the Windos 7 x64 couldn’t find a proper device driver for the built-in LCD screen and just installed Generic PnP display driver.

When a proper device driver is installed, it registers its device name. However, in the “Generic PnP display” driver case, it doesn’t register itself as “LCD”. So, the CreateFile() can’t create a handle to an LCD screen with that device name.

Then, what is a proper name for the unregistered device? It is not documented in any MSDN document. However, with help of querydosdevice program, I could find out the device name.

This is the device name.

So, in a source code, you will access the unregistered device like this.

// 1. Query the Backlight supported device
// IOCTL_VIDEO_QUERY_SUPPORTED_BRIGHTNESS s
HANDLE hLCDScreen;
hLCDScreen = CreateFile( _T("\\\\.\\DISPLAY#APP9C5F#4&30ca27f4&0&UID67568640#{e6f07b5f-ee97-4a90-b076-33f57bf4eaa7}"), GENERIC_READ,			// No access to the drive 
						FILE_SHARE_READ | FILE_SHARE_WRITE,	// share mode
						NULL,								// default security attributes
						OPEN_EXISTING,						// Disposition
						0,
						NULL );
if( hLCDScreen == INVALID_HANDLE_VALUE )
{
	dwError = GetLastError();
	TRACE1( "CreateFile() error(%d)\n", dwError );

	return;
}

However, the Generic PnP Display driver doesn’t support brightness level. So, I couldn’t write any more codes to control the brightness.

Can anyone tell me what chipset MacBook with Intel GMA 940 uses for LCD screen? or tell me where I can find a proper device driver?

CreateEx() and Create() for CDockablePane

Historically CreateEx() has been thought as Create() with additional functionality like more styles.
So, if you take a look at many MFC classes which provide CreateEx() and Create(), you can see that CreateEx() calls Create() and do more chores to provide added functionality.

However, I found out that CDockablePane’s doesn’t.
Although MSDN document shows that there is CreateEx() for CDockablePane, it actually doesn’t exist.
So, you shouldn’t be fooled by the MSDN document and create CDockablePane with CreateEx() and wonder why it doesn’t work.

Storing a pointer value in a non-pointer variable vs. Storing general value in a pointer variable : INT_PTR, LONG_PTR etc vs. MAKEINTRESOURCE

If you are a programmer who studied C/C++ after Windows 95, you may not know the existence of windows data types like INT_PTR, LONG_PTR, because you don’t really need to use it.

So, when you have a chance to port legacy codes to x64 platform, you may  fail in considering proper porting of variables declared with those or variables which don’t use them but semantically means the same.

At StackOverFlow, there is good explanation on this subject.

DWORD_PTR, INT_PTR, LONG_PTR, UINT_PTR, ULONG_PTR When, How and Why?

However, I would like to add more comment.

During MS DOS era, many programmers wrote codes in a way that the longest data type available on his/her machine to store addresses or pointer values. There were a little reason for that. For example, you want to do somewhat mathematical calculation with addresses without bordering with the width of the data type.
To me, it has been always better to calculate on addresses with the width of data type in mind, but there are some other cases you should have disregard the width of data type and just calculate something. It was kind of high technique for doing something weird. ( Some can be, while others are not. )

Some Windows API functions and member functions still require to use such convention. They ask you to pass address value to a variable which is not pointer variables. For that purpose, they use *_PTR.

So, I noticed that not a few programmers, who don’t know history, tended to fail in porting legacy code to x64.

Also, there is opposite example.
This time, it is to store non-pointer value to a pointer variable. Such an example is MAKEINTRESOURCE() macro.

#define MAKEINTRESOURCE(i)(LPTSTR)((DWORD)((WORD)(i)))

So, it takes an integer number for a resource like resource ID for a bitmap or an icon, and converts it to pointer to string (LPTSTR).

So, if you are one of new guys who don’t know its history, just get familiar with this and don’t be puzzled!

%d bloggers like this: