Is it possible to write to the desktop space from a .NET application?

I would like to be able to write directly to the XP/2003 desktop to provide various information, such as disk space, calendar, network information. I have tried using a dynamic web page and scripting, but I always get prompted to allow access of the ActiveX control to the local system (which is fair enough but a problem here). I have tried to look through the .net framework, but cannot see a way to write to the desktop area.  The information would need to be set during login or dynamically there after.  It is not a problem having an app that is running either from startup or as a service.

Anything that is written to the desktop should be under any icons etc on the desktop.

I intend to write this in VB.NET.

Any help would be much appreciated.

Thanks
John




Answer this question

Is it possible to write to the desktop space from a .NET application?

  • prasanna.k

    I have been able to get the desktop handle and I can get an image of the screen.  I am concerned that this includes any apps loaded, as I just need to write to the background image.

    The following code has three functions/subs.  One to write to the form via a handle which works OK. Two that tries to write to the desktop, but nothing happens. Three that gets an image of the screen.  Here is the code:


    Public Class Form1

    Inherits System.Windows.Forms.Form

    Public Declare Function GetDesktopWindow Lib "user32" () As IntPtr

    Public Declare Function GetDC Lib "user32" (ByVal hwnd As IntPtr) As IntPtr

    Public Declare Function ReleaseDC Lib "user32" (ByVal hwnd As IntPtr, ByVal hdc As IntPtr) As Integer

    Public Declare Function StretchBlt Lib "gdi32" (ByVal hDC As IntPtr, ByVal x As Integer, ByVal y As Integer, ByVal nWidth As Integer, ByVal nHeight As Integer, ByVal hSrcDC As IntPtr, ByVal xSrc As Integer, ByVal ySrc As Integer, ByVal nSrcWidth As Integer, ByVal nSrcHeight As Integer, ByVal dwRop As Integer) As Integer

    #Region " Windows Form Designer generated code "

    Public Sub New()

    MyBase.New()

    'This call is required by the Windows Form Designer.

    InitializeComponent()

    'Add any initialization after the InitializeComponent() call

    End Sub

    'Form overrides dispose to clean up the component list.

    Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)

    If disposing Then

    If Not (components Is Nothing) Then

    components.Dispose()

    End If

    End If

    MyBase.Dispose(disposing)

    End Sub

    'Required by the Windows Form Designer

    Private components As System.ComponentModel.IContainer

    'NOTE: The following procedure is required by the Windows Form Designer

    'It can be modified using the Windows Form Designer.

    'Do not modify it using the code editor.

    Friend WithEvents butDraw As System.Windows.Forms.Button

    Friend WithEvents PictureBox1 As System.Windows.Forms.PictureBox

    Friend WithEvents Button1 As System.Windows.Forms.Button

    <System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()

    Me.butDraw = New System.Windows.Forms.Button

    Me.PictureBox1 = New System.Windows.Forms.PictureBox

    Me.Button1 = New System.Windows.Forms.Button

    Me.SuspendLayout()

    '

    'butDraw

    '

    Me.butDraw.Location = New System.Drawing.Point(0, 0)

    Me.butDraw.Name = "butDraw"

    Me.butDraw.Size = New System.Drawing.Size(80, 32)

    Me.butDraw.TabIndex = 0

    Me.butDraw.Text = "Draw"

    '

    'PictureBox1

    '

    Me.PictureBox1.Location = New System.Drawing.Point(48, 120)

    Me.PictureBox1.Name = "PictureBox1"

    Me.PictureBox1.Size = New System.Drawing.Size(448, 280)

    Me.PictureBox1.TabIndex = 1

    Me.PictureBox1.TabStop = False

    '

    'Button1

    '

    Me.Button1.Location = New System.Drawing.Point(80, 0)

    Me.Button1.Name = "Button1"

    Me.Button1.Size = New System.Drawing.Size(80, 32)

    Me.Button1.TabIndex = 2

    Me.Button1.Text = "Text"

    '

    'Form1

    '

    Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)

    Me.ClientSize = New System.Drawing.Size(536, 438)

    Me.Controls.Add(Me.Button1)

    Me.Controls.Add(Me.PictureBox1)

    Me.Controls.Add(Me.butDraw)

    Me.Name = "Form1"

    Me.Text = "Form1"

    Me.ResumeLayout(False)

    End Sub

    #End Region

    Private Sub butDraw_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles butDraw.Click

    PictureBox1.Image = DesktopImage()

    End Sub

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

    PrintTextOnForm()

    PrintTextOnDesktop()

    End Sub

    Private Sub PrintTextOnForm()

    '##### Write on form

    Dim formGraphics As System.drawing.Graphics = System.Drawing.Graphics.FromHwnd(Me.Handle)

    Dim drawString As String = "Sample Text"

    Dim drawFont As New System.Drawing.Font("Arial", 16)

    Dim drawBrush As New System.Drawing.SolidBrush(System.Drawing.Color.Black)

    Dim x As Single = 150.0

    Dim y As Single = 50.0

    Dim drawFormat As New System.Drawing.StringFormat

    formGraphics.DrawString(drawString, drawFont, drawBrush, x, y, drawFormat)

    formGraphics.DrawRectangle(New Pen(Color.Red, 3), 0, 0, 200, 100)

    drawFont.Dispose()

    drawBrush.Dispose()

    formGraphics.Dispose()

    End Sub

    Private Sub PrintTextOnDesktop()

    '##### Write on desktop

    Dim desktop_win As IntPtr = GetDesktopWindow

    Dim desktop_dc As IntPtr = GetDC(desktop_win)

    '------------

    Dim formGraphics As System.drawing.Graphics = System.Drawing.Graphics.FromHwnd(desktop_win)

    Dim drawString As String = "On the desktop "

    Dim drawFont As New System.Drawing.Font("Arial", 16)

    Dim drawBrush As New System.Drawing.SolidBrush(System.Drawing.Color.Black)

    Dim x As Single = 150.0

    Dim y As Single = 50.0

    Dim drawFormat As New System.Drawing.StringFormat

    formGraphics.DrawString(drawString, drawFont, drawBrush, x, y, drawFormat)

    formGraphics.DrawRectangle(New Pen(Color.Red, 3), 0, 0, 200, 100)

    drawFont.Dispose()

    drawBrush.Dispose()

    formGraphics.Dispose()

    '------------------

    ' Release the desktop's DC.

    ReleaseDC(desktop_win, desktop_dc)

    End Sub

    Private Function DesktopImage() As Bitmap

    Dim SRCCOPY As Integer = &HCC0020 ' Hex

    ' Get the desktop size in pixels.

    Dim desktop_win As IntPtr = GetDesktopWindow

    Dim desktop_dc As IntPtr = GetDC(desktop_win)

    '------------

    Dim formGraphics As System.drawing.Graphics = System.Drawing.Graphics.FromHwnd(GetDesktopWindow)

    Dim drawString As String = "On the desktop "

    Dim drawFont As New System.Drawing.Font("Arial", 16)

    Dim drawBrush As New System.Drawing.SolidBrush(System.Drawing.Color.Black)

    Dim x As Single = 150.0

    Dim y As Single = 50.0

    Dim drawFormat As New System.Drawing.StringFormat

    formGraphics.DrawString(drawString, drawFont, drawBrush, x, y, drawFormat)

    drawFont.Dispose()

    drawBrush.Dispose()

    formGraphics.Dispose()

    '------------------

    Dim desktop_bounds As Rectangle = Screen.GetBounds(New Point(1, 1))

    Dim desktop_wid As Int32 = desktop_bounds.Width

    Dim desktop_hgt As Int32 = desktop_bounds.Height

    ' Make a Bitmap to hold the image.

    Dim bm As New Bitmap(desktop_wid, desktop_hgt)

    Dim bm_gr As Graphics = Graphics.FromImage(bm)

    Dim bm_hdc As IntPtr = bm_gr.GetHdc

    ' Copy the desktop's image.

    StretchBlt(bm_hdc, 0, 0, desktop_wid, desktop_hgt, _

    desktop_dc, 0, 0, desktop_wid, desktop_hgt, _

    SRCCOPY)

    ' Release the bitmap's and desktop's DCs.

    bm_gr.ReleaseHdc(bm_hdc)

    ReleaseDC(desktop_win, desktop_dc)

    ' Return the result.

    Return bm

    End Function

    End Class


     


  • Bill (Australia-Melbourne)

    Thanks RichS

    Yes it is the first option that I require, so I will need to get the handle of the desktop.  I am hoping that this will not write over any desktop icons. I am going to write this in VB.  Any examples to get me going would be great, but at least I know where to head now.

  • ShowMeTheMoney

    Do you want to write to the desktop background ( hence whatever you show will be underneath any other windows ), or do you want to have something that is always on-top of every other window

    Both are possible, but require different approaches.

    Desktop Background:
    You can grab the handle to the desktop window - I cant remember the code at the moment but I've written something to do this somewhere.  From the handle you can get the graphics object and then draw to that.  However, by using this approach means that the info will only be fully visible if all windows are minimized!!

    TopMostWindow:
    This is slightly easier.  But means that your info will always be over the top of any other window.  To make this less of a problem you can make your window transparent ( using Opacity property of your form ), and you can make your window invisible to mouseclicks - see below for this code.  If you do make it invisible to mouse clicks then you will probably want to create a NotifyTray icon so you can access settings / close your app.

    regards,
    RichS


    ClickThrough Code ( C# ):

    You will need to add the Interop.Get/SetWindowLong function ( see www.pinvoke.net ) and add "public const long WS_EX_TRANSPARENT = 0x00000020L;" and "public const int GWL_EXSTYLE = (-20);"


          // Add the WS_EX_TRANSPARENT Style
          long lStyle = Interop.GetWindowLong( this.Handle, Interop.GWL_EXSTYLE );
          lStyle |= ( Interop.WS_EX_TRANSPARENT );
          Interop.SetWindowLong(
    this.Handle, Interop.GWL_EXSTYLE, lStyle );   


          // Remove the WS_EX_TRANSPARENT Style
          long lStyle = Interop.GetWindowLong( this.Handle, Interop.GWL_EXSTYLE );
          lStyle &= ( ~Interop.WS_EX_TRANSPARENT );
          Interop.SetWindowLong(
    this.Handle, Interop.GWL_EXSTYLE, lStyle );


  • Is it possible to write to the desktop space from a .NET application?