文本和字体

 

 

 

 

 

 

 

 

 

解题:
一、在用户区的某个坐标位置打印一行字符串
二、在用户区的中心位置打印一行字符串,位置始终不变
三、读取一个纯文本文件(FILE)内容到用户区中,(保持格式)


BeginPaint(HWND hWnd,LPPAINTSTRUCT lpPaint);:获取HDC句柄,其中LPPAINTSTRUCT lpPaint,是一个指向PAINTSTRUCT的指针。

PAINTSTRUCT结构:特别之处在于,它记录需要重绘的矩形区域(比如被遮盖的无效区域),在接收WM_PAINT消息时,重绘这个区域。

关于重绘的几个问题,第一,不是所有区域都需要重绘(比如标题栏,工具条等等),只是无效区域需要重绘。windows又如何知道重绘区域的大小呢?在BeginPaint()函数中,将无效区域的大小写在PAINTSTRUCT结构中。

typedef struct tagPAINTSTRUCT {
    HDC         hdc;/*标识显示设备对象的句柄*/
    BOOL        fErase;/*若为非零,说明用户背景已被重画,否则未被重画*/
    RECT        rcPaint;/*指定要求重画的矩形区域的左上角和右下角的坐标*/
    BOOL        fRestore;
    BOOL        fIncUpdate;
    BYTE        rgbReserved[32];
} PAINTSTRUCT, *PPAINTSTRUCT, *NPPAINTSTRUCT, *LPPAINTSTRUCT;

InvalidateRect()函数强制某个区域为无效区域。

InvalidateRect(
    HWND hWnd ,
    CONST RECT *lpRect, /*无效区域坐标,如果为NULL,则整个用户区无效*/
    BOOL bErase);/*是否擦除RECT所标示的区域内容*/

TextOut函数(文本输出):

BOOL TextOut
(
    HDC hdc;
    int x;/*串起始点的逻辑x坐标值*/
    int y;/*串起始点的逻辑y坐标值*/
    LPSTR lpString;/*指向字符串的指针*/
    int nCount)/*绘制的字符个数*/

EndPaint(),两个作用:第一,返回借用的设备对象,第二,清除消息队列中的WM_PAINT消息。

具体的在用户区中显示文本的几种特别方法:
(1)要求文本始终居于用户区的正中间

//DrawText()函数用于格式化显示文本

这种方法的一个缺点在于,只要产生WM_PAINT消息时,就需要计算用户区域的大小,但实际情况下用户区域的大小很少去动,这种计算显的多余。

改进:在windows窗口的大小发生改变时,会发送WM_SIZE(一个知识点)消息,直接进入消息队列,其中,在消息的附加参数lParam中,低位表示最后的宽度,高位表示最后的高度,通过对lParam的分离,得到窗口最后的宽高。然后借用这个矩形坐标显示文本,也能达成目的。

case WM_SIZE:
         rect.right=LOWORD(lParam);/*分离宽度*/
         rect.bottom=HIWORD(lParam);/*分离高度*/
         break;

 

 关于字体

字体的信息图:

BOOL GetTextMetrics(HDC hdc,LPTEXTMETRICS lpMetric);
/*得到设备对象使用字体的尺寸,并存入到TEXTMETRICS的变量中*/

/*--------------完整代码-----------------*/

//-------------------程序包含的内容如下:---------------------//

//创建窗口时产生的第一条消息:WM_CREATE;
//获取设备DC:BeginPaint(),EndPaint(),InvalidateRect()..
//获取用户区的区域大小..GetClientRect()
//自定义用户消息,SendMessage()的使用;

//窗口改变时,产生的WM_SIZE消息
//如何检测鼠标双键按下的消息
//文本输出:TextOut(),格式化输出:DrawText()

//3个小例子
//一、在用户区的某个坐标位置打印字符串
//二、始终在用户区区域的中心位置显示某个字符串
//三、读取一个文本文件,并在用户区显示

//---------------------------------------------------------------//

#include "stdio.h"
#include <windows.h>

#define WM_MYMSG WM_USER+100 /*自定义消息的ID*/

LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;/*回调函数声明*/

int _stdcall WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,PSTR szCmdLine, int iCmdShow)
{
     static char szAppName[] = TEXT ("HelloWin") ;
     HWND         hwnd ;                //窗口句柄
     MSG          msg ;                 //消息结构
     WNDCLASS     wndclass ;            //窗口类结构
     wndclass.style         = CS_HREDRAW | CS_VREDRAW ;
     wndclass.lpfnWndProc   = WndProc ;
     wndclass.cbClsExtra    = 0 ;
     wndclass.cbWndExtra    = 0 ;
     wndclass.hInstance     = hInstance ;
     wndclass.hIcon         = LoadIcon (NULL, IDI_WARNING) ;//加载图标
     wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ;    //加载鼠标指针
     wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;//获取一个图形对象
     wndclass.lpszMenuName  = NULL ;
     wndclass.lpszClassName = szAppName ;

     RegisterClass (&wndclass);//注册窗口(类)
     
     hwnd = CreateWindow (szAppName,//创建窗口                  
                          TEXT ("一个简单的Win32程序"), 
                          WS_OVERLAPPEDWINDOW,        
                          CW_USEDEFAULT,              
                          CW_USEDEFAULT,              
                          CW_USEDEFAULT,             
                          CW_USEDEFAULT,              
                          NULL,                      
                          NULL,                       
                          hInstance,                  
                          NULL) ;                     
     /*在此处发出第一个消息WM_CREATE*/
     ShowWindow (hwnd, iCmdShow) ;          //显示窗口     
     UpdateWindow (hwnd) ;                  //窗口刷新
     /*在此处发出第一个WM_PAINT消息*/
     
     while (GetMessage (&msg, NULL, 0, 0))            //从消息队列中获取消息
     {
          TranslateMessage (&msg) ;                   //转换某些键盘消息
          DispatchMessage (&msg) ;                    //将消息发送给窗口过程
     }
     return msg.wParam ;
}

LRESULT  CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{   
    HDC hdc;
    const static char msg[]="hello,welcome to Windows!";
    static RECT rect;/*静态矩形区域*/
    PAINTSTRUCT ps;
    static int xChar,yChar;
    char szBuffer[256];
    int line=0;
    TEXTMETRIC tm;//字体尺寸信息结构体
    FILE *fp;
    
     switch(message)
     {   
     case WM_CREATE://窗口创建的第一条消息:WM_CREATE         
            /*hdc=GetDC(hwnd);

            //GetDC()只能用于非WM_PAINT消息,原因是即使释放DC之后,并不能清除WM_PAINT消息

            GetTextMetrics(hdc,&tm);//获取字体的相关信息,并存放在变量tm中;
            xChar=tm.tmAveCharWidth;//字符的平均宽度
            yChar=tm.tmHeight+tm.tmExternalLeading;/*高度=字符高度+默认行距,此高度作为打印行的间距
            ReleaseDC(hwnd,hdc);*/
         break;

     case WM_SIZE:/*窗口大小接收到的消息*/
         rect.right=LOWORD(lParam);//分离宽度
         rect.bottom=HIWORD(lParam);//分离高度
         
         break;

     case WM_PAINT:   
         //InvalidateRect(hwnd,NULL,0);/*强制整个用户区为无效区域*/
         hdc=BeginPaint(hwnd,&ps);
         //TextOut(hdc,10,20,msg,strlen(msg));
         GetClientRect(hwnd,&rect);//获取用户区的区域坐标,放在矩形变量rect中;
         DrawText(hdc,msg,-1,&rect,DT_SINGLELINE | DT_CENTER | DT_VCENTER);

            /*if((fp=fopen("disp.txt","r"))==NULL) //需要在当前目录下建立一个disp.c文件
            {
                TextOut(hdc,0,0,"打开错误!",8);//一个汉字两字节//
                break;
            }
            else
        {
            while(!feof(fp))
            {    
                int i=0;
                char ch;
                while((ch=fgetc(fp))!='\n' && ch!=EOF)
                szBuffer[i++]=char(ch);
                TextOut(hdc,xChar,line*yChar,szBuffer,i);//打印文件,每一行控制间距//
                line++;
            }
            fclose(fp);
        }*/
         EndPaint(hwnd,&ps);//EndPaint()可以清除消息队列中的WM_PAINT消息
          break;

     case WM_MYMSG:/*自定义消息*/
        MessageBox(NULL,"用户自定义消息","自定义",MB_OK);
        break;

     case WM_LBUTTONDOWN:/*鼠标左键按下后发送自定义消息WM_MYMSG*/
         SendMessage(hwnd,WM_MYMSG,wParam,lParam);
         break;

     //case WM_LBUTTONDOWN:/*双键检测*/
         //if(wParam & MK_RBUTTON)
         //SendMessage(hwnd,WM_MYMSG,wParam,lParam);
         //break;

     case WM_DESTROY:
          PostQuitMessage (0) ; //在消息队列中插入一条“退出”消息
         break;
     }
     return DefWindowProc (hwnd, message, wParam, lParam);//执行默认的消息处理
}
View Code

 

GetDC()和BeginPaint()的区别

GetDC()通过ReleaseDC()释放后,但不能清除WM_PAINT消息,所以适合在非WM_PAINT消息中创建,EndPaint()可以清除WM_PAINT消息。

 

转载于:https://www.cnblogs.com/tinaluo/p/5388666.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值