C++ 如何在没有窗口的情况下绘制文本

C++ 如何在没有窗口的情况下绘制文本,c++,winapi,C++,Winapi,我试图在屏幕上显示文本,在所有内容之上,不可点击,没有任何窗口。其目的是能够显示通知。我有点接近我想要的,但一个非常奇怪的问题刚刚出现。代码如下: #include <Windows.h> int main(void){ HDC hdc = ::GetDC(0); RECT rect; SetTextColor(hdc, RGB(0, 0, 255)); SetBkMode(hdc, TRANSPARENT); SetBkColor(h

我试图在屏幕上显示文本,在所有内容之上,不可点击,没有任何窗口。其目的是能够显示通知。我有点接近我想要的,但一个非常奇怪的问题刚刚出现。代码如下:

#include <Windows.h>  

int main(void){

    HDC hdc = ::GetDC(0);
    RECT rect;
    SetTextColor(hdc, RGB(0, 0, 255));
    SetBkMode(hdc, TRANSPARENT);
    SetBkColor(hdc, RGB(0, 0, 0));
    auto hFont = CreateFont(40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, L"Verdana");
    auto hTmp = (HFONT)SelectObject(hdc, hFont);
    rect.left = 40;
    rect.top = 10;

    while (true){
        DrawText(hdc, L"THIS IS A TEXT", -1, &rect, DT_SINGLELINE | DT_NOCLIP);
        Sleep(1);
    }
    DeleteObject(SelectObject(hdc, hTmp));
    ::ReleaseDC(0, hdc);
    return 0;

}
#包括
内部主(空){
HDC-HDC=::GetDC(0);
RECT-RECT;
SetTextColor(hdc,RGB(0,0255));
SetBkMode(hdc,透明);
SetBkColor(hdc,RGB(0,0,0));
auto-hFont=CreateFont(40,0,0,0,0,0,0,0,0,0,2,0,L“Verdana”);
自动hTmp=(HFONT)选择对象(hdc,HFONT);
rect.left=40;
rect.top=10;
while(true){
DrawText(hdc,L“这是一个文本”,-1,&rect,DT|u SINGLELINE | DT|u NOCLIP);
睡眠(1);
}
DeleteObject(SelectObject(hdc,hTmp));
::ReleaseDC(0,hdc);
返回0;
}
这就是当我将文本设置从
red
更改为
blue
并将大小
80
更改为
40
时发生的情况:

由于某种原因,在重新运行程序后,我仍然可以看到旧文本,它告诉我我误解了某些内容。有没有更好更干净的方法


编辑:我检查了windows通知,但这不是一个解决方案。假设你正在玩一个全屏游戏,想知道是否有电子邮件到达。另一个重要的事情是它不能被点击,所以错误的点击不会使你的游戏最小化。当你接到电话时,skype弹出窗口会最小化你的应用程序,这有多烦人?

你已经绕过了所有的窗口/客户端控件,因此系统不知道这个区域需要清除。您需要手动告诉它,尤其是因为您没有使用windows消息通知机制

在绘制之前,您希望使屏幕的该部分无效,并告诉windows重新绘制它:

::InvalidateRect (0, &rect, false);   //  Redraw without erasing. If doesn't help, try true
::UpdateWindow (0);
while (true)...

您已绕过所有windows/客户端控件,因此系统不知道需要清除此区域。您需要手动告诉它,尤其是因为您没有使用windows消息通知机制

在绘制之前,您希望使屏幕的该部分无效,并告诉windows重新绘制它:

::InvalidateRect (0, &rect, false);   //  Redraw without erasing. If doesn't help, try true
::UpdateWindow (0);
while (true)...

我在努力工作时遇到了很多问题。如果有人最终访问此页面,寻找我遇到的相同问题的答案,我希望你过得比我轻松。这是对我有用的代码:

#include <Windows.h> 


INT WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
    PSTR lpCmdLine, INT nCmdShow)
{
    // Define and initialize variables
    HDC          hdc;
    HDC          hdcMem;
    HBITMAP      hbmMem;
    HANDLE       hOld;
    RECT rect;
    SIZE sz;
    int win_width = 0;
    int win_height = 0;
    int font_size = 20;
    int location_x = 40;
    int location_y = 40;
    int border = font_size / 4;
    int duration = 10000;           // In miliseconds. The notification will always stay up more time
    wchar_t* font_face = L"Consolas";
    wchar_t message[100];

    // Save command-line arguments to message; They are showed by the notification
    MultiByteToWideChar(0, 0,
        lpCmdLine,
        strlen(lpCmdLine),
        message,
        100
        );
    message[strlen(lpCmdLine)] = L'\0';


    // Acquire screen
    hdc = ::GetDC(0);

    //Create necessary font
    HFONT hFont = CreateFont(font_size, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, font_face);
    HFONT hTmp = (HFONT)SelectObject(hdc, hFont);

    // Calculate size of the text
    GetTextExtentPoint32(hdc, message, wcslen(message), &sz);
    win_width = sz.cx;
    win_height = sz.cy;
    rect = { 0, 0, sz.cx, sz.cx };

    // Create an off-screen DC for double-buffering
    hdcMem = CreateCompatibleDC(hdc);
    hbmMem = CreateCompatibleBitmap(hdc, win_width + 2 * border, win_height + 2 * border);

    // Configure off-screen DC
    SetBkMode(hdcMem, OPAQUE);
    SetTextColor(hdcMem, RGB(125, 125, 255));
    SetBkColor(hdcMem, RGB(0, 0, 0));
    SelectObject(hdcMem, hFont);
    hOld = SelectObject(hdcMem, hbmMem);

    // Draw loop
    for (int i = 0; i < duration; i++)
    {
        // Draw into hdcMem
        DrawText(hdcMem, message, -1, &rect, DT_SINGLELINE);

        // Transfer the off-screen DC to the screen
        BitBlt(hdc, location_x, location_y, win_width + 2 * border, win_height + 2 * border, hdcMem, -5, -5, SRCCOPY);


        // Don't eat all the cpu!
        Sleep(1);
    }

    // Delete notification right after time expires
    ::InvalidateRect(0, &rect, false);
    ::UpdateWindow(0);

    // Free-up the off-screen DC
    SelectObject(hdcMem, hOld);
    DeleteObject(hbmMem);
    DeleteDC(hdcMem);

    // Release created objects
    DeleteObject(SelectObject(hdc, hTmp));
    ::ReleaseDC(0, hdc);
    return 0;
}
#包括
INT WinMain(HINSTANCE HINSTANCE,HINSTANCE hPrevInstance,
PSTR lpCmdLine,INT nCmdShow)
{
//定义和初始化变量
HDC-HDC;
HDC-hdcMem;
HBITMAP-hbmMem;
把手;
RECT-RECT;
尺寸sz;
int win_width=0;
int win_高度=0;
int font_size=20;
int位置_x=40;
int位置_y=40;
int border=字体大小/4;
int duration=10000;//以毫秒为单位。通知将始终保留更长的时间
wchar_t*font_face=L“控制台”;
wchar__t消息[100];
//将命令行参数保存到消息;它们由通知显示
MultiByteToWideChar(0,0,
lpCmdLine,
斯特伦(lpCmdLine),
消息
100
);
消息[strlen(lpCmdLine)]=L'\0';
//获取屏幕
hdc=::GetDC(0);
//创建必要的字体
HFONT HFONT=CreateFont(字体大小,0,0,0,0,0,0,0,0,0,0,2,0,字体面);
HFONT hTmp=(HFONT)选择对象(hdc,HFONT);
//计算文本的大小
GetTextExtentPoint32(hdc、消息、wcslen(消息)和sz);
win_width=sz.cx;
win_height=sz.cy;
rect={0,0,sz.cx,sz.cx};
//为双缓冲创建屏幕外DC
hdcMem=CreateCompatibleDC(hdc);
hbmMem=CreateCompatibleBitmap(hdc、win_宽度+2*边框、win_高度+2*边框);
//配置屏幕外DC
SetBkMode(hdcMem,不透明);
SetTextColor(hdcMem、RGB(125、125、255));
SetBkColor(hdcMem,RGB(0,0,0));
选择对象(hdcMem、hFont);
按住=选择对象(hdcMem、hbmMem);
//拉环
for(int i=0;i
它仍然可以改进,很多。唯一显示的是带有通知的矩形。
传递给程序的参数将显示为消息。实现了与
hdcMem
相关的所有内容,以避免闪烁。我还不能更改较大矩形的背景。

我在尝试进行此操作时遇到了很多问题。如果有人最终访问此页面,寻找我遇到的相同问题的答案,我希望你过得比我轻松。这是对我有用的代码:

#include <Windows.h> 


INT WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
    PSTR lpCmdLine, INT nCmdShow)
{
    // Define and initialize variables
    HDC          hdc;
    HDC          hdcMem;
    HBITMAP      hbmMem;
    HANDLE       hOld;
    RECT rect;
    SIZE sz;
    int win_width = 0;
    int win_height = 0;
    int font_size = 20;
    int location_x = 40;
    int location_y = 40;
    int border = font_size / 4;
    int duration = 10000;           // In miliseconds. The notification will always stay up more time
    wchar_t* font_face = L"Consolas";
    wchar_t message[100];

    // Save command-line arguments to message; They are showed by the notification
    MultiByteToWideChar(0, 0,
        lpCmdLine,
        strlen(lpCmdLine),
        message,
        100
        );
    message[strlen(lpCmdLine)] = L'\0';


    // Acquire screen
    hdc = ::GetDC(0);

    //Create necessary font
    HFONT hFont = CreateFont(font_size, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, font_face);
    HFONT hTmp = (HFONT)SelectObject(hdc, hFont);

    // Calculate size of the text
    GetTextExtentPoint32(hdc, message, wcslen(message), &sz);
    win_width = sz.cx;
    win_height = sz.cy;
    rect = { 0, 0, sz.cx, sz.cx };

    // Create an off-screen DC for double-buffering
    hdcMem = CreateCompatibleDC(hdc);
    hbmMem = CreateCompatibleBitmap(hdc, win_width + 2 * border, win_height + 2 * border);

    // Configure off-screen DC
    SetBkMode(hdcMem, OPAQUE);
    SetTextColor(hdcMem, RGB(125, 125, 255));
    SetBkColor(hdcMem, RGB(0, 0, 0));
    SelectObject(hdcMem, hFont);
    hOld = SelectObject(hdcMem, hbmMem);

    // Draw loop
    for (int i = 0; i < duration; i++)
    {
        // Draw into hdcMem
        DrawText(hdcMem, message, -1, &rect, DT_SINGLELINE);

        // Transfer the off-screen DC to the screen
        BitBlt(hdc, location_x, location_y, win_width + 2 * border, win_height + 2 * border, hdcMem, -5, -5, SRCCOPY);


        // Don't eat all the cpu!
        Sleep(1);
    }

    // Delete notification right after time expires
    ::InvalidateRect(0, &rect, false);
    ::UpdateWindow(0);

    // Free-up the off-screen DC
    SelectObject(hdcMem, hOld);
    DeleteObject(hbmMem);
    DeleteDC(hdcMem);

    // Release created objects
    DeleteObject(SelectObject(hdc, hTmp));
    ::ReleaseDC(0, hdc);
    return 0;
}
#包括
INT WinMain(HINSTANCE HINSTANCE,HINSTANCE hPrevInstance,
PSTR lpCmdLine,INT nCmdShow)
{
//定义和初始化变量
HDC-HDC;
HDC-hdcMem;
HBITMAP-hbmMem;
把手;
RECT-RECT;
尺寸sz;
int win_width=0;
int win_高度=0;
int font_size=20;
int位置_x=40;
int位置_y=40;
int border=字体大小/4;
int duration=10000;//以毫秒为单位。通知将始终保留更长的时间
wchar_t*font_face=L“控制台”;
wchar__t消息[100];
//保存通信