Windows API:在屏幕显示上写入屏幕

时间:2015-03-17 03:54:12

标签: windows winapi screen

我正在写一个(非常)小的应用程序,它只是在开始时执行一些小的操作,应该在屏幕上写一条消息,类似于屏幕显示:大字母,没有任何窗口,高于一切,可见某个时刻然后逐渐消失。

如果可能,我不想为它创建一个窗口。

这样做的正确方法是什么?

(我希望没有像DirectX这样的特殊工具包,需要直接图形访问等)

2 个答案:

答案 0 :(得分:8)

正如评论中指出的那样,您可以直接绘制到屏幕上。 GetDC提供返回适当的设备上下文:

  

hWnd [in]

     

要检索其DC的窗口的句柄。 如果此值为NULL,则GetDC将检索整个屏幕的DC。

直接渲染到屏幕会产生至少两个需要解决的问题:

  1. 屏幕DC是共享资源。每当其他人渲染到屏幕上时(例如,当显示一个窗口时),屏幕的那部分就会被覆盖。
  2. 渲染具有破坏性。渲染到设备上下文时,原始内容会被覆盖。要实现淡出效果,您必须保存原始内容(并在显示其他窗口时动态更新它们)。
  3. 这两个问题都可以通过创建窗口来解决。窗口不需要具有边框,标题栏,系统菜单或最小化/最大化/关闭按钮。相应的Window StylesWS_POPUP | WS_VISIBLE

    要使窗口显示在其他所有内容之前,需要将其标记为最顶层(使用WS_EX_TOPMOST Extended Window Style)。请注意,这会将窗口置于Z顺序中所有其他非最顶层窗口的上方。你仍然需要与其他最顶级的窗户战斗(你无法赢得的军备竞赛)。

    要实现透明度,窗口必须具有WS_EX_LAYERED扩展窗口样式以创建Layered Window。然后调用SetLayeredWindowAttributes启用Alpha透明度。为了使窗口背景完全透明,无论窗口的alpha透明度如何,您还需要启用颜色键控。一种简单的方法是将WNDCLASSEX structurehbrBackground成员设置为(HBRUSH)GetStockObject(BLACK_BRUSH),并在调用{RGB(0, 0, 0)中指定crKey参数{1}}。

    <小时/> 概念证明(错误检查简称为简洁):

    SetLayeredWindowAttributes

    首先注册主应用程序窗口类。重要的是#define STRICT 1 #define WIN32_LEAN_AND_MEAN #include <SDKDDKVer.h> #include <windows.h> // Forward declarations LRESULT CALLBACK WndProc( HWND, UINT, WPARAM, LPARAM ); // Entry point int APIENTRY wWinMain( HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPTSTR /*lpCmdLine*/, int nCmdShow ) { 成员。这可以控制背景渲染,并最终使其完全透明。

    hbrBackground

    这是实例化窗口并调整其属性所需的所有设置代码。启用Alpha透明度以准备淡出效果,而颜色键控遮盖了窗口中未渲染的区域。

        const wchar_t k_WndClassName[] = L"OverlayWindowClass";
    
        // Register window class
        WNDCLASSEXW wcex = { 0 };
        wcex.cbSize = sizeof( wcex );
        wcex.style          = CS_HREDRAW | CS_VREDRAW;
        wcex.lpfnWndProc    = WndProc;
        wcex.hInstance      = hInstance;
        wcex.hCursor        = ::LoadCursorW( NULL, IDC_ARROW );
        wcex.hbrBackground  = (HBRUSH)::GetStockObject( BLACK_BRUSH );
        wcex.lpszClassName  = k_WndClassName;
        ::RegisterClassExW( &wcex );
    

    HWND hWnd = ::CreateWindowExW( WS_EX_TOPMOST | WS_EX_LAYERED, k_WndClassName, L"Overlay Window", WS_POPUP | WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT, 800, 600, NULL, NULL, hInstance, NULL ); // Make window semi-transparent, and mask out background color ::SetLayeredWindowAttributes( hWnd, RGB( 0, 0, 0 ), 128, LWA_ALPHA | LWA_COLORKEY ); 的剩余部分是样板窗口应用程序代码。

    wWinMain

    窗口过程执行简单渲染。为了演示alpha和键颜色透明度,代码呈现一个白色椭圆,客户区域为边界矩形。此外,还处理WM_NCHITTEST message,以提供使用鼠标或其他指针设备在屏幕上拖动窗口的简单方法。请注意,鼠标输入将传递到下面的窗口,用于完全透明的所有区域。

        ::ShowWindow( hWnd, nCmdShow );
        ::UpdateWindow( hWnd );
    
        // Main message loop:
        MSG msg = { 0 };
        while ( ::GetMessageW( &msg, NULL, 0, 0 ) > 0 )
        {
            ::TranslateMessage( &msg );
            ::DispatchMessageW( &msg );
        }
    
        return (int)msg.wParam;
    }
    

    <小时/> 备用LRESULT CALLBACK WndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam ) { switch ( message ) { case WM_PAINT: { PAINTSTRUCT ps = { 0 }; HDC hDC = ::BeginPaint( hWnd, &ps ); RECT rc = { 0 }; ::GetClientRect( hWnd, &rc ); HBRUSH hbrOld = (HBRUSH)::SelectObject( hDC, ::GetStockObject( WHITE_BRUSH ) ); ::Ellipse( hDC, rc.left, rc.top, rc.right, rc.bottom ); ::SelectObject( hDC, hbrOld ); ::EndPaint( hWnd, &ps ); } return 0; case WM_NCHITTEST: return HTCAPTION; case WM_DESTROY: ::PostQuitMessage( 0 ); return 0; default: break; } return ::DefWindowProc( hWnd, message, wParam, lParam ); } 处理程序,用于输出文本。使用与键颜色不同的文本颜色非常重要。如果要使用黑色文本,则必须使用不同的键颜色。

    WM_PAINT

答案 1 :(得分:0)

我还希望能够直接写入屏幕(在示例中是显示实际的 Windows 版本信息)。我做了很多搜索,终于能够拼凑出代码......

Imports System.Environment

Public Class frmMain
    Dim stringFont As Font
    Dim string_format As New StringFormat()

    Dim my_WinName As String
    Const my_WinStatic As String = " ver. "
    Dim my_WinVersion As String
    Dim my_WinRelease As String
    Dim my_WinBuild As String
    Dim my_WinSubBuild As String
    Dim my_Delim1 As String
    Dim emb_Delim1 As Boolean
    Dim my_Delim2 As String
    Dim emb_Delim2 As Boolean
    Dim txt_Display_Ver As String
    Dim txt_Curr_Build As String
    Dim txt_UBR_Value As String
    Dim the_File As String
    Dim version_Complete As Boolean
    Dim current_Ver As String
    Dim previous_Ver As String

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        Try
            If My.Settings.UpgradeRequired = True Then
                My.Settings.Upgrade()
                My.Settings.UpgradeRequired = False
                My.Settings.Save()
            End If
        Catch ex As Exception
            MessageBox.Show(ex.Message, "Upgrade from Previous Version Error")
        End Try

        conMenuAbout.Text = My.Application.Info.AssemblyName & "  (ver. " & My.Application.Info.Version.ToString & ")"
        prop_Grid.SelectedObject = My.Settings

        string_format.Alignment = StringAlignment.Far
        string_format.LineAlignment = StringAlignment.Near

        version_Complete = False

        form_Defaults()

        Me.WindowState = FormWindowState.Minimized

        nextTime.Interval = 500
        nextTime.Start()
    End Sub

    Private Sub nextTime_Tick(sender As Object, e As EventArgs) Handles nextTime.Tick
        Dim d As Graphics = Graphics.FromHwnd(IntPtr.Zero)

        Dim brush_Name As System.Drawing.Brush = New System.Drawing.SolidBrush(My.Settings.color_Win_Name)
        Dim brush_Static As System.Drawing.Brush = New System.Drawing.SolidBrush(My.Settings.color_static_Ver)
        Dim brush_WinVer As System.Drawing.Brush = New System.Drawing.SolidBrush(My.Settings.color_Win_Version)
        Dim brush_CharDelim As System.Drawing.Brush = New System.Drawing.SolidBrush(My.Settings.color_Char_Delim)
        Dim brush_Curr_Rel As System.Drawing.Brush = New System.Drawing.SolidBrush(My.Settings.color_Curr_Release)
        Dim brush_Curr_Bld As System.Drawing.Brush = New System.Drawing.SolidBrush(My.Settings.color_Curr_Build)
        Dim brush_UBR_Delim As System.Drawing.Brush = New System.Drawing.SolidBrush(My.Settings.color_UBR_Delim)
        Dim brush_UBR_Rev As System.Drawing.Brush = New System.Drawing.SolidBrush(My.Settings.color_UpdateBldRev)

        update_Version()

        Dim writeHere As New PointF(Screen.PrimaryScreen.Bounds.Right - 300, Screen.PrimaryScreen.Bounds.Bottom - 64)
        d.DrawString(my_WinName, stringFont, brush_Name, writeHere)

        writeHere.X += d.MeasureString(my_WinName, stringFont).Width - My.Settings.Space_1
        d.DrawString(my_WinStatic, stringFont, brush_Static, writeHere)

        writeHere.X += d.MeasureString(my_WinStatic, stringFont).Width - My.Settings.Space_2
        d.DrawString(my_WinVersion, stringFont, brush_WinVer, writeHere)

        writeHere.X += d.MeasureString(my_WinVersion, stringFont).Width - My.Settings.Space_3
        d.DrawString(my_Delim1, stringFont, brush_CharDelim, writeHere)

        writeHere.X += d.MeasureString(my_Delim1, stringFont).Width - My.Settings.Space_4
        d.DrawString(my_WinRelease, stringFont, brush_Curr_Rel, writeHere)

        writeHere.X += d.MeasureString(my_WinRelease, stringFont).Width - My.Settings.Space_5
        d.DrawString(my_Delim1, stringFont, brush_CharDelim, writeHere)

        writeHere.X += d.MeasureString(my_Delim1, stringFont).Width - My.Settings.Space_6
        d.DrawString(my_WinBuild, stringFont, brush_Curr_Bld, writeHere)

        writeHere.X += d.MeasureString(my_WinBuild, stringFont).Width - My.Settings.Space_7
        d.DrawString(my_Delim2, stringFont, brush_UBR_Delim, writeHere)

        writeHere.X += d.MeasureString(my_Delim2, stringFont).Width - My.Settings.Space_8
        d.DrawString(my_WinSubBuild, stringFont, brush_UBR_Rev, writeHere)

    End Sub

    Public Sub form_Defaults()

        Try
            nextTime.Interval = My.Settings.updateInterval
            Me.Opacity = My.Settings.Opacity / 100
            my_Delim1 = My.Settings.char_Delimiter
            emb_Delim1 = My.Settings.embolden_Char_Delim
            my_Delim2 = My.Settings.UBR_Delimiter
            emb_Delim2 = My.Settings.embolden_UBR_Char
        Catch ex As Exception
            MessageBox.Show(ex.Message)
        End Try

        update_Version()

        If current_Ver <> previous_Ver Then
            Try
                If Not String.IsNullOrEmpty(My.Settings.text_Version_File) Then
                    the_File = My.Settings.text_Version_File
                Else
                    ofd.FileName = "WinVer.txt"
                    If ofd.ShowDialog = DialogResult.OK Then
                        My.Settings.text_Version_File = ofd.FileName
                        the_File = ofd.FileName
                    End If
                End If
            Catch ex As Exception
                Dim str_Err = ex.Message
                ofd.FileName = "WinVer.txt"
                If ofd.ShowDialog = DialogResult.OK Then
                    My.Settings.text_Version_File = ofd.FileName
                    the_File = ofd.FileName
                End If
            End Try
            conMenuSaveVer_Click(Nothing, Nothing)
            previous_Ver = current_Ver
        End If

    End Sub

    Private Sub update_Version()
        Try
            Dim tmpStr As String = My.Computer.Registry.GetValue("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion", "ProductName", Nothing)
            my_WinName = Replace(tmpStr, "Windows ", "Win ")
            tmpStr = Replace(my_WinName, "Professional", "Pro")
            my_WinName = Replace(tmpStr, "Enterprise", "Pro")
            my_WinVersion = My.Computer.Registry.GetValue("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion", "CurrentVersion", Nothing)
            my_WinRelease = My.Computer.Registry.GetValue("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion", "DisplayVersion", Nothing)
            my_WinBuild = My.Computer.Registry.GetValue("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion", "CurrentBuild", Nothing)
            Dim myKey As Microsoft.Win32.RegistryKey = Microsoft.Win32.RegistryKey.OpenBaseKey(Microsoft.Win32.RegistryHive.LocalMachine, Microsoft.Win32.RegistryView.Registry64)
            Dim myKey2 As Object = myKey.OpenSubKey("SOFTWARE\Microsoft\Windows NT\CurrentVersion")
            Dim myVal As Int64 = Convert.ToInt64(myKey2.GetValue("UBR").ToString)
            my_WinSubBuild = myVal
            current_Ver = my_WinName & my_WinVersion & my_WinRelease & my_WinBuild & my_WinSubBuild
            stringFont = New Font(My.Settings.useFont, My.Settings.useFont.Style)
            version_Complete = True
        Catch ex As Exception
            MessageBox.Show(ex.Message)
        End Try
    End Sub

    Private Sub conMenuExit_Click(sender As Object, e As EventArgs) Handles conMenuExit.Click
        Application.Exit()
    End Sub

    Private Sub conMenuSettings_Click(sender As Object, e As EventArgs) Handles conMenuSettings.Click
        Me.WindowState = FormWindowState.Normal
    End Sub

    Private Sub frmMain_Resize(sender As Object, e As EventArgs) Handles MyBase.Resize
        If Me.WindowState = FormWindowState.Minimized Then
            Me.sysTrayIcon.Visible = True
            Me.ShowInTaskbar = False
        Else
            Me.ShowInTaskbar = True
            Me.sysTrayIcon.Visible = False
        End If
    End Sub

    Private Sub frmMain_FormClosing(sender As Object, e As FormClosingEventArgs) Handles MyBase.FormClosing
        e.Cancel = True
        Me.WindowState = FormWindowState.Minimized
    End Sub

    Private Sub conMenuSaveVer_Click(sender As Object, e As EventArgs) Handles conMenuSaveVer.Click
        If version_Complete = False Then
            Exit Sub
        End If

        Try
            My.Computer.FileSystem.WriteAllText(the_File, current_Ver, False)
        Catch ex As Exception
            MessageBox.Show(Me, ex.Message, "Save Version Error")
        End Try

        Try
            If Not String.IsNullOrEmpty(current_Ver) Then
                If Not String.IsNullOrWhiteSpace(current_Ver) Then
                    Clipboard.SetText(current_Ver)
                End If
            End If
        Catch ex As Exception
            MessageBox.Show(Me, ex.Message, "Clipboard Error")
        End Try
    End Sub

End Class