先行说明:
工程简要说明
说明下,这个工程一共5个文件(两个头文件,三个资源文件):
头文件中,一个是宏定义用文件【WinMacro.h】,另一个是函数声明用文件【WinHead.h】;
资源文件中,一个是窗口注册文件(基本可以忽略)【WinMain.c】,第二个是窗口过程文件【WinProc.c】,最后一个里是函数定义文件(主要出错的地方)【WinSupport.c】。
编译器介绍
这里我用的是Dev c++ (v.5.11)编译器,有段时间入了学生联赛的坑,然后现在就有点停不下来,对VC没什么好感,emmm。
对于ERROR的探索
我本来是希望用TextOut函数做一个模拟DrawText函数的新函数:TextPrint,后续还想给它添加一些独特的输出特效,不过现在看来都运行不了(一运行就立即报错,但是编译没问题),尴尬。
万恶的Dev c++调试功能有问题,找了很长时间解决办法之后,就调试了一下,结果就...完全看不懂了。
在下面我标注的【图6】第27行(WinSupport.c)这里单步调试会终止,并弹出显示:
program received signal SIGFPE, Airthmetic expection
然后会显示 Windows CPU 运行表(大概是这个叫法...),但还是看不懂。所以我后面修改了代码,把27、28行都改成了将那两个变量赋值为常数2,而不是即时计算。
顺便改了一下74行,把pcText换成了pChar (74行这里是自己发现的逻辑错误)。
现在各位看到的代码是最初的版本,上面的修改在下面附的代码里都未体现。不是说我懒的修改,而是因为我想把这里弄明白,到底是什么原因。
修改后的代码其实也有问题,那就是虽然可以运行,但是假如在一个矩形内输出了n(n>1)行,那么只有第一行能被保留(啊啊啊,要疯了!!!)
最终预期功能
嗯,这里在重申一下,那个TextPrint函数是低配版的DrawText函数,功能就是指定一个矩形,然后向矩形范围内输出(每行填满后自动换行)(假如要输出的内容填满了整个矩形都没有输出完,那就停止输出)。
一些个人看法
自己也试了许多次,但就是不太清楚其中机理,只好劳烦各位“达人”了。
我是直接看书自学的WinAPI,没什么耐性,就先用刚学的新函数TextOut练练手, 所以...挖了个大坑。
个人感觉应该是WinAPI"可重入"的锅,但是实在是没有接触过面向对象的编程(只会一点C),so......
致谢
(.-..-.)刚刚注册的号,学生党一枚,初次提问,言谢在先!
源代码:
【WinMacro.h】:
#define CLASSNAME "Program: Get Seated"
#define APPNAME "Tiny Spotlessness: The Seats"
#define SIZE_101 SIZEOFSTRING
#define SIZEOFSTRING 100
#define EMPTY INITIAL
#define INITIAL 0
#define CXSCREEN GetSystemMetrics (SM_CXSCREEN)
#define CYSCREEN GetSystemMetrics (SM_CYSCREEN)
#define FAULTMSG_101 FAULTMSG_WNDNTNEEDED
#define FAULTMSG_WNDNTNEEDED "Fault 101: WindowsNTneeded!"
【图1】
【WinHead.h】:
/*----------------------------------------------------------------
Supporting Header Files
-----------------------------------------------------------------*/
#include <windows.h>
#include <stdbool.h>
#include "WinMacro.h"
/*----------------------------------------------------------------
Supporting Value Structions
-----------------------------------------------------------------*/
/*----------------------------------------------------------------
Supporting Function Statements
-----------------------------------------------------------------*/
LRESULT CALLBACK WndProc ( /*--------------------------------------*/
HWND hwnd, /* Stating the Main Window Process, */
UINT message, /* a special function with four para- */
WPARAM wParam, /* meters, using the other functions. */
LPARAM lParam /*--------------------------------------*/
);
int TextPrint( /*--------------------------------------*/
HDC hdc, /* Print on any place of rect, using */
RECT *pRect, /* a pointer to rect and a pointer to */
const TEXTMETRIC *pTm, /* the text metric, a string with */
const TCHAR *pcText, /* its length, and return the number */
int iLenth /* of the characters outputted. */
);
【图2】
【图3】
【WinMain.c】:
/*--------------------------------------
WinMain.c, (c) Shen Pengfei, 2019
--------------------------------------*/
#include "WinHead.h"
int WINAPI WinMain (
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
PSTR szCmdLine,
int iCmdShow
) {
TCHAR szClassName[] = TEXT (CLASSNAME);
TCHAR szAppName[] = TEXT (APPNAME);
HWND hwnd;
MSG msg;
WNDCLASS wndclass;
wndclass.style = CS_HREDRAW | CS_VREDRAW;
wndclass.lpfnWndProc = WndProc;
wndclass.cbClsExtra = EMPTY;
wndclass.cbWndExtra = EMPTY;
wndclass.hInstance = hInstance;
wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION);
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW);
wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH);
wndclass.lpszClassName = szClassName;
wndclass.lpszMenuName = NULL;
if (!RegisterClass (&wndclass)) {
MessageBox (
NULL,
TEXT (FAULTMSG_WNDNTNEEDED),
szAppName,
MB_ICONERROR
);
return EMPTY;
}
hwnd = CreateWindow (
szClassName, /* window class name */
szAppName, /* window caption name */
WS_OVERLAPPEDWINDOW | WS_VSCROLL, /* window style */
INITIAL, /* initial x position */
INITIAL, /* initial y position */
CXSCREEN, /* initial x size */
CYSCREEN, /* initial y size */
NULL, /* parent window handle */
NULL, /* window menu handle */
hInstance, /* program instance handle */
NULL /* creation parameters */
);
ShowWindow (hwnd, iCmdShow);
UpdateWindow (hwnd);
while (GetMessage (&msg, NULL, EMPTY, EMPTY)) {
TranslateMessage (&msg);
DispatchMessage (&msg);
}
return msg.wParam;
}
【图4】
【图5】
【WinSupport.c】:
/*------------------------------------------------
(c) Shen PengFei, 2019
A file to set up some functions to complite
some special tasks.
-------------------------------------------------*/
#include "WinHead.h"
int TextPrint (
HDC hdc,
RECT *pRect,
const TEXTMETRIC *pTm,
const TCHAR *pcText,
int iLenth
) {
static int iLine;
static int iRaw;
static int iCount;
static const TCHAR *pChar;
/*--------------------------------------------
Count the width and the Height of the
screen, by the way, creating a pointer
copying the address of initial string
---------------------------------------------*/
iLine = (pRect->right - pRect->left) / pTm->tmAveCharWidth;
iRaw = (pRect->bottom - pRect->top) / (pTm->tmHeight + pTm->tmExternalLeading);
pChar = pcText;
for (
iCount = INITIAL;
/*------------------------------------------------
To prevent the number of charaters outputt
-ed on the screen from overring the string's,
check if the result value of [PCHAR minus
PCTEXT] was not larger than the length of
the string. And also, to prevent the strin
-g's overring the initial rect, check if the
raw number over the max value counted and
called IRAW.
-------------------------------------------------*/
pChar - pcText < iLenth &&
iCount <= iRaw;
/*------------------------------------------------
Change the outputting address of each raw,
the position of the changed pointer to the
string and Add the cyclelatte times value
in turn each time, to end the running in
time.
-------------------------------------------------*/
pRect->top += pTm->tmHeight + pTm->tmExternalLeading,
pChar += iLine,
iCount ++
) {
/*-----------------------------------------------
Solve the special condition that outputted
characters' last raw is not enough to make
the whole raw full, while may cause that
the stuffs behind the address of the string
fluent the system running.
------------------------------------------------*/
if (
iLenth % iLine != EMPTY &&
iCount == iLenth / iLine
) iLine = iLenth % iLine;
TextOut (
hdc,
pRect->left,
pRect->top,
pcText,
iLine
);
}
/* Return the initial value used in turn */
pRect->left = pRect->top = INITIAL;
return pChar - pcText;
}
【图6】
【图7】
【图8】
【WinProc.c】:
/*-----------------------------------------------
(c) Shen Pengfei, 2019
A file to create a series of windows, used by
WINMAIN.C .
------------------------------------------------*/
#include "WinHead.h"
LRESULT CALLBACK WndProc (
HWND hwnd,
UINT message,
WPARAM wParam,
LPARAM lParam
) {
static int cxChar;
static int cyChar;
static RECT rectPrint;
static TCHAR szText [SIZEOFSTRING];
HDC hdc;
RECT rect;
PAINTSTRUCT ps;
TEXTMETRIC tm;
switch (message) {
case WM_CREATE:
rectPrint.left = INITIAL;
rectPrint.top = INITIAL;
rectPrint.right = CXSCREEN;
rectPrint.bottom = CYSCREEN;
hdc = GetDC (hwnd);
/*-----------------------------------------
To get the text parameters on its
width and height (may with the external
leading).
------------------------------------------*/
GetTextMetrics (hdc, &tm);
cxChar = tm.tmAveCharWidth;
cyChar = tm.tmHeight + tm.tmExternalLeading;
ReleaseDC (hwnd, hdc);
return EMPTY;
case WM_SIZE :
rectPrint.right = LOWORD (lParam);
rectPrint.bottom = HIWORD (lParam);
return EMPTY;
case WM_PAINT:
hdc = BeginPaint (hwnd, &ps);
/* Debugging part */
TextPrint (
hdc,
&rectPrint,
&tm,
szText,
wsprintf (
szText,
TEXT ("sdaf")
)
);
EndPaint (hwnd, &ps);
return EMPTY;
case WM_DESTROY:
PostQuitMessage (EMPTY);
return EMPTY;
}
return DefWindowProc (hwnd, message, wParam, lParam);
}
【图9】
【图10】