Ureader.com  
Microsoft software help and Community
   home   |   control panel login   |   archive   |  
 
Windos
win32.3rdparty
win32.directx.audio
win32.directx.ddk
win32.directx.graphics
win32.directx.input
win32.directx.managed
win32.directx.misc
win32.directx.networking
win32.directx.sdk
win32.directx.video
win32.dirx.grap.shaders
win32.gdi
win32.international
win32.kernel
win32.messaging
win32.mmedia
win32.networks
win32.ole
win32.rtc
win32.tapi
win32.tapi.beta
win32.tools
win32.ui
win32.wince
win32.wmi
windows.mediacenter
winfx.aero
winfx.announcements
winfx.avalon
winfx.collaboration
winfx.fundamentals
winfx.general
winfx.indigo
winfx.sdk
winfx.winfs
  
 
date: Sat, 12 Jul 2008 13:55:01 -0700,    group: microsoft.public.win32.programmer.ui        back       


Richedit EM_FORMATRANGE bug/wierdness   
According to http://msdn.microsoft.com/en-us/library/bb788020(VS.85).aspx

The return value for EM_FORMATRANGE is "the index of the last character that 
fits in the region, plus 1"

I have created a sample that proves that this documentation is incorrect or 
that there is a bug in the control.

The documentation is correct in the general case but if you try to use a 
FORMATRANGE rc that isn't tall enough for the first line, EM_FORMATRANGE 
always acts as though the first line fits.

// formatrange.cpp : Defines the entry point for the application.
//

#include "stdafx.h"
#include "formatrange.h"
#include <commctrl.h>
#include <richedit.h>
#include <stdio.h>

#define MAX_LOADSTRING 100

// Global Variables:
HINSTANCE hInst;								// current instance
TCHAR szTitle[MAX_LOADSTRING];					// The title bar text
TCHAR szWindowClass[MAX_LOADSTRING];			// the main window class name

// Forward declarations of functions included in this code module:
ATOM				MyRegisterClass(HINSTANCE hInstance);
BOOL				InitInstance(HINSTANCE, int);
LRESULT CALLBACK	WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK	About(HWND, UINT, WPARAM, LPARAM);

int APIENTRY _tWinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPTSTR    lpCmdLine,
                     int       nCmdShow)
{
	UNREFERENCED_PARAMETER(hPrevInstance);
	UNREFERENCED_PARAMETER(lpCmdLine);

 	// TODO: Place code here.
	MSG msg;
	HACCEL hAccelTable;

    InitCommonControls();

	// Initialize global strings
	LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
	LoadString(hInstance, IDC_FORMATRANGE, szWindowClass, MAX_LOADSTRING);
	MyRegisterClass(hInstance);

	// Perform application initialization:
	if (!InitInstance (hInstance, nCmdShow))
	{
		return FALSE;
	}

	hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_FORMATRANGE));

	// Main message loop:
	while (GetMessage(&msg, NULL, 0, 0))
	{
		if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
		{
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
	}

	return (int) msg.wParam;
}



//
//  FUNCTION: MyRegisterClass()
//
//  PURPOSE: Registers the window class.
//
//  COMMENTS:
//
//    This function and its usage are only necessary if you want this code
//    to be compatible with Win32 systems prior to the 'RegisterClassEx'
//    function that was added to Windows 95. It is important to call this 
function
//    so that the application will get 'well formed' small icons associated
//    with it.
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
	WNDCLASSEX wcex;

	wcex.cbSize = sizeof(WNDCLASSEX);

	wcex.style			= CS_HREDRAW | CS_VREDRAW;
	wcex.lpfnWndProc	= WndProc;
	wcex.cbClsExtra		= 0;
	wcex.cbWndExtra		= 0;
	wcex.hInstance		= hInstance;
	wcex.hIcon			= LoadIcon(hInstance, MAKEINTRESOURCE(IDI_FORMATRANGE));
	wcex.hCursor		= LoadCursor(NULL, IDC_ARROW);
	wcex.hbrBackground	= (HBRUSH)(COLOR_WINDOW+1);
	wcex.lpszMenuName	= MAKEINTRESOURCE(IDC_FORMATRANGE);
	wcex.lpszClassName	= szWindowClass;
	wcex.hIconSm		= LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));

	return RegisterClassEx(&wcex);
}

//
//   FUNCTION: InitInstance(HINSTANCE, int)
//
//   PURPOSE: Saves instance handle and creates main window
//
//   COMMENTS:
//
//        In this function, we save the instance handle in a global variable 
and
//        create and display the main program window.
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
   HWND hWnd;

   hInst = hInstance; // Store instance handle in our global variable

   hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
      CW_USEDEFAULT, 0, 400, 400, NULL, NULL, hInstance, NULL);

   if (!hWnd)
   {
      return FALSE;
   }

   ShowWindow(hWnd, nCmdShow);
   UpdateWindow(hWnd);

   SetTimer(hWnd,1,100,0);

   return TRUE;
}

//
//  FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM)
//
//  PURPOSE:  Processes messages for the main window.
//
//  WM_COMMAND	- process the application menu
//  WM_PAINT	- Paint the main window
//  WM_DESTROY	- post a quit message and return
//
//

HWND g_hWndEdit = 0;
int g_pixels_y = 200; 

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM 
lParam)
{
	int wmId, wmEvent;
	PAINTSTRUCT ps;
	HDC hdc;

	switch (message)
	{
	case WM_COMMAND:
		wmId    = LOWORD(wParam);
		wmEvent = HIWORD(wParam);
		// Parse the menu selections:
        switch ( wmEvent )
        {
        case EN_CHANGE:
            InvalidateRect(hWnd,0,TRUE);
            break; 
        }
		switch (wmId)
		{
		case IDM_ABOUT:
			DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
			break;
		case IDM_EXIT:
			DestroyWindow(hWnd);
			break;
		default:
			return DefWindowProc(hWnd, message, wParam, lParam);
		}
		break;
	case WM_PAINT:
        {
		    hdc = BeginPaint(hWnd, &ps);

            // Create "print preview". 
            SendMessage(g_hWndEdit, EM_SETTARGETDEVICE, (WPARAM)hdc, 200);

            int ppi_x = GetDeviceCaps(hdc,LOGPIXELSX);
            int ppi_y = GetDeviceCaps(hdc,LOGPIXELSX);
            int pixels_x = 200;
            // 16 pixels per line
            // leave room for 3.5 lines

            FORMATRANGE fr;
            fr.hdc = hdc;
            fr.hdcTarget = hdc;
            fr.rc.left = 0;
            fr.rc.right = 1440*pixels_x/ppi_x; // convert pixels to twips
            fr.rc.top = 0;
            fr.rc.bottom = 1440*g_pixels_y/ppi_y; // convert pixels to twips
            fr.rcPage = fr.rc;
            fr.chrg.cpMin = 0;
            fr.chrg.cpMax = GetWindowTextLength(g_hWndEdit);

            int lastCharacter = (int)SendMessage(g_hWndEdit, EM_FORMATRANGE, 
TRUE, (LPARAM)&fr);
            SendMessage(g_hWndEdit, EM_FORMATRANGE, FALSE, 0);
            WCHAR buf[128];
            wsprintf( buf, L"lastCharacter == %i\n", lastCharacter );

            RECT rect = {0,0,pixels_x,g_pixels_y};
            HBRUSH hbr = CreateSolidBrush( RGB(0,0,0) );
            FrameRect(hdc,&rect,hbr);
            DeleteObject(hbr);

            rect.top = g_pixels_y+30;
            rect.bottom = rect.top + 100;
            DrawText(hdc,buf,-1,&rect,0);

            EndPaint(hWnd, &ps);
            SendMessage(g_hWndEdit, EM_SETTARGETDEVICE, 0, 0);

        }
		break;
	case WM_TIMER:
        if ( g_pixels_y > 0 )
        {
            g_pixels_y--;
            InvalidateRect(hWnd,0,TRUE);
        }
        break;
	case WM_DESTROY:
		PostQuitMessage(0);
		break;
	case WM_CREATE:
        {
            LoadLibrary(TEXT("msftedit.dll"));
            DWORD dwStyle = ES_MULTILINE | WS_VISIBLE | WS_CHILD | WS_BORDER 
| WS_TABSTOP;
            g_hWndEdit = CreateWindow( TEXT("RICHEDIT50W"), TEXT("line 1 is 
very long to test wrapping and EM_FORMATRANGE\r\nline 2\r\nline 3\r\nline 
4\r\n"), dwStyle, 200, 200, 200, 200, hWnd, 0, GetModuleHandle(0), 0 );
            SendMessage( g_hWndEdit, EM_SETSEL,0,-1);
            CHARFORMAT cf;
            ZeroMemory(&cf,sizeof(cf));
            cf.cbSize = sizeof(cf);
            cf.dwMask = CFM_SIZE | CFM_FACE;
            int font_pixels = 18;
            cf.yHeight = 1440*font_pixels/96; // convert pixels to twips
            wcscpy( cf.szFaceName, L"Tahoma" );
            SendMessage( g_hWndEdit, EM_SETCHARFORMAT, SCF_SELECTION, 
(LPARAM)&cf );
        }
		break;
	default:
		return DefWindowProc(hWnd, message, wParam, lParam);
	}
	return 0;
}

// Message handler for about box.
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
	UNREFERENCED_PARAMETER(lParam);
	switch (message)
	{
	case WM_INITDIALOG:
		return (INT_PTR)TRUE;

	case WM_COMMAND:
		if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
		{
			EndDialog(hDlg, LOWORD(wParam));
			return (INT_PTR)TRUE;
		}
		break;
	}
	return (INT_PTR)FALSE;
}
date: Sat, 12 Jul 2008 13:55:01 -0700   author:   Vince Harron

Google
 
Web ureader.com


    COPYRIGHT 2007, YARDI TECHNOLOGY LIMITED, ALL RIGHT RESERVE  |   contact us