I have a country map in a picture box with provincial divisions. I can fill each province on mouse over by calling following floodfill function on my pictureBox MouseMove event:
Private Structure BITMAPINFOHEADER
Dim biSize As Integer
Dim biWidth As Integer
Dim biHeight As Integer
Dim biPlanes As Short
Dim biBitCount As Short
Dim biCompression As Integer
Dim biSizeImage As Integer
Dim biXPelsPerMeter As Integer
Dim biYPelsPerMeter As Integer
Dim biClrUsed As Integer
Dim biClrImportant As Integer
End Structure
''' <summary>
''' API declarations
''' </summary>
''' <param name="hdc"></param>
''' <returns></returns>
''' <remarks></remarks>
Private Declare Function CreateCompatibleDC Lib "gdi32" (ByVal hdc As IntPtr) As IntPtr
Private Declare Function CreateDIBSection Lib "gdi32" (ByVal hdc As IntPtr, ByRef pBitmapInfo As BITMAPINFOHEADER, ByVal un As Integer, ByRef lplpVoid As IntPtr, ByVal handle As Integer, ByVal dw As Integer) As IntPtr
Private Declare Function BitBlt Lib "gdi32" (ByVal hDestDC 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 dwRop As Integer) As Integer
Private Declare Function ExtFloodFill Lib "gdi32" (ByVal hdc As IntPtr, ByVal X As Integer, ByVal Y As Integer, ByVal crColor As Integer, ByVal wFillType As Integer) As Integer
Private Declare Function CreateSolidBrush Lib "gdi32" (ByVal crColor As Integer) As IntPtr
Private Declare Function GetPixel Lib "gdi32" (ByVal hdc As IntPtr, ByVal X As Integer, ByVal Y As Integer) As Integer
Private Declare Function SelectObject Lib "gdi32" (ByVal hdc As IntPtr, ByVal hObject As IntPtr) As IntPtr
Private Declare Function DeleteObject Lib "gdi32" (ByVal hObject As IntPtr) As Integer
Private Declare Function DeleteDC Lib "gdi32" (ByVal hdc As IntPtr) As Integer
Private Declare Function GdiFlush Lib "gdi32" Alias "GdiFlush" () As Integer
Private Const SRCCOPY = &HCC0020
Public Sub FloodFill(ByRef mbmp As Bitmap, ByVal col As Color, ByVal Pt As Point)
If mbmp Is Nothing Then Exit Sub
Dim srcDC As IntPtr = CreateCompatibleDC(IntPtr.Zero)
Dim dstDC As IntPtr = CreateCompatibleDC(IntPtr.Zero)
Dim dstBMI As BITMAPINFOHEADER
With dstBMI
.biBitCount = 24
.biHeight = mbmp.Height
.biSize = System.Runtime.InteropServices.Marshal.SizeOf(dstBMI)
.biWidth = mbmp.Width
.biPlanes = 1
End With
Dim dstBits As IntPtr
Dim mbmpGetHbitmap As IntPtr = mbmp.GetHbitmap
'Select the bitmap into an HDC
Dim Obmp As IntPtr = SelectObject(srcDC, mbmpGetHbitmap)
'Create a DIB
Dim dstBMP As IntPtr = CreateDIBSection(dstDC, dstBMI, 0, dstBits, 0, 0)
Dim Obmp2 As IntPtr = SelectObject(dstDC, dstBMP)
'Place our bitmap in the DIB
BitBlt(dstDC, 0, 0, mbmp.Width, mbmp.Height, srcDC, 0, 0, SRCCOPY)
GdiFlush()
'Create a brush to use to FloodFill
Dim mBrush As IntPtr = CreateSolidBrush(System.Drawing.ColorTranslator.ToOle(col))
Dim hmm As IntPtr = SelectObject(dstDC, mBrush)
'Label5.Text = mBrush
'Fill with color
ExtFloodFill(dstDC, Pt.X, Pt.Y, GetPixel(dstDC, Pt.X, Pt.Y), 1)
'Get the bitmap back with the Filled Color
mbmp = Bitmap.FromHbitmap(dstBMP)
'Go berserk clearing memory
'ExtFloodFill has a bad reputation for gobbling up memory
'if you dont clean up properly
DeleteObject(mBrush)
DeleteObject(SelectObject(dstDC, mBrush))
DeleteObject(SelectObject(dstDC, dstBMP))
DeleteObject(SelectObject(srcDC, mbmpGetHbitmap))
DeleteObject(hmm)
DeleteObject(dstBits)
DeleteObject(Obmp2)
DeleteObject(Obmp)
DeleteObject(dstBMP)
DeleteDC(dstDC)
DeleteDC(srcDC)
mbmpGetHbitmap = Nothing
hmm = Nothing
dstBits = Nothing
Obmp2 = Nothing
Obmp = Nothing
dstBMP = Nothing
dstDC = Nothing
srcDC = Nothing
dstBMI = Nothing
End Sub
the only thing I need is to recognize floodfilled province on mouse over. any suggestion?
If you know the map coordinates you could do bounds checking on a defined list of rectangles.
i.e. a class which has a name as string and a rectangle
so washington might be (0,0,100,100)
and new york might be (100,40,100,100)
then just look through your list of objects and bounds check them
return the "name" of the area to the user
if that is what you were trying to achieve.
p.s. i'm not sure why you're using alot of "classic" blitting / GDI code where the .NET framework system.drawing namespace could be much nicer for you....
dim b as New Bitmap(Width, Height, Imaging.PixelFormat.Format32bppPArgb)
dim g as graphics = graphics.fromimage(b)
g.Clear(Color.White)
g.DrawImage(Bitmap.FromFile("test.jpg"), New Rectangle(0, 0, 100, 100))
PictureBox1.image = b
Related
I would like to get the scaling factor of a secondary screen.
With this piece of code I get the right information for the primary monitor:
Private Declare Function GetDeviceCaps Lib "gdi32.dll" (ByVal hdc As IntPtr, ByVal nIndex As Integer) As Integer
Private Declare Function GetDCEx Lib "user32.dll" (ByVal hWnd As IntPtr, ByVal hrgnClip As IntPtr, ByVal DeviceContextValues As DeviceContextValues) As IntPtr
Dim desktop As IntPtr = GetDCEx(0, 0, DeviceContextValues.Window)
Dim scalling As Double = GetDeviceCaps(desktop, 118) / GetDeviceCaps(desktop, 8)
But how can I get the same information for the 2nd monitor?
Which parameters in the GetDCEx function?
thanks it's help me this is the solution :
<DllImport("gdi32.dll")>
Public Shared Function GetDeviceCaps(ByVal hDC As IntPtr, ByVal nIndex As Integer) As Integer
End Function
<DllImport("gdi32.dll", SetLastError:=True, CharSet:=CharSet.Ansi)>
Public Shared Function CreateDC(<MarshalAs(UnmanagedType.LPStr)> lpszDriver As String,
<MarshalAs(UnmanagedType.LPStr)> lpszDevice As String,
<MarshalAs(UnmanagedType.LPStr)> lpszOutput As String,
lpInitData As IntPtr) As IntPtr
End Function
Public Shared Function GetScalleFactor(index As Integer) As Double
Dim desktop As IntPtr = CreateDC(Screen.AllScreens(index).DeviceName, Nothing, Nothing, IntPtr.Zero)
Return GetDeviceCaps(desktop, 118) / GetDeviceCaps(desktop, 8)
End Function
I Tried to convert this code into vb.net and add a little code to make a file... but the file's resolution became crap and i cant seem to insert it into the Crystal report, Did i do something wrong while converting it into vb.net? thanks in advance :)
Here is the original link Convert an image into WMF with .NET?
<Flags>
Private Enum EmfToWmfBitsFlags
EmfToWmfBitsFlagsDefault = &H0
EmfToWmfBitsFlagsEmbedEmf = &H1
EmfToWmfBitsFlagsIncludePlaceable = &H2
EmfToWmfBitsFlagsNoXORClip = &H4
End Enum
Private Shared MM_ISOTROPIC As Integer = 7
Private Shared MM_ANISOTROPIC As Integer = 8
<DllImport("gdiplus.dll")>
Private Shared Function GdipEmfToWmfBits(_hEmf As IntPtr, _bufferSize As UInteger, _buffer As Byte(), _mappingMode As Integer, _flags As EmfToWmfBitsFlags) As UInteger
End Function
<DllImport("gdi32.dll")>
Private Shared Function SetMetaFileBitsEx(_bufferSize As UInteger, _buffer As Byte()) As IntPtr
End Function
<DllImport("gdi32.dll")>
Private Shared Function CopyMetaFile(hWmf As IntPtr, filename As String) As IntPtr
End Function
<DllImport("gdi32.dll")>
Private Shared Function DeleteMetaFile(hWmf As IntPtr) As Boolean
End Function
<DllImport("gdi32.dll")>
Private Shared Function DeleteEnhMetaFile(hEmf As IntPtr) As Boolean
End Function
Private Function MakeMetafileStream(image As Bitmap) As Byte()
Dim metafile As Metafile = Nothing
Using g As Graphics = Graphics.FromImage(image)
Dim hDC As IntPtr = g.GetHdc()
metafile = New Metafile(hDC, EmfType.EmfOnly)
g.ReleaseHdc(hDC)
End Using
Using g As Graphics = Graphics.FromImage(metafile)
g.DrawImage(image, 0, 0)
End Using
Dim _hEmf As IntPtr = metafile.GetHenhmetafile()
Dim _bufferSize As UInteger = GdipEmfToWmfBits(_hEmf, 0, Nothing, MM_ANISOTROPIC, EmfToWmfBitsFlags.EmfToWmfBitsFlagsDefault)
Dim _buffer As Byte() = New Byte(_bufferSize - 1) {}
GdipEmfToWmfBits(_hEmf, _bufferSize, _buffer, MM_ANISOTROPIC, EmfToWmfBitsFlags.EmfToWmfBitsFlagsDefault)
Dim hmf As IntPtr = SetMetaFileBitsEx(_bufferSize, _buffer)
Dim tempfile As String = Path.GetTempFileName()
CopyMetaFile(hmf, tempfile)
DeleteMetaFile(hmf)
DeleteEnhMetaFile(_hEmf)
Dim stream = New MemoryStream()
Dim data As Byte() = File.ReadAllBytes(tempfile)
Return data
End Function
Private Sub Convert()
Dim src As New Bitmap("C:\Users\Sample\Desktop\Logos\LogoTransparent\Transparentlogo.png")
Dim Msteam As Byte() = MakeMetafileStream(src)
Dim newF As String = "C:\Users\Alvin Rodriguez\Desktop\Logos\new logo transparent\Transparentlogo.wmf"
System.IO.File.WriteAllBytes(newF, Msteam)
Msteam = Nothing
End Sub
Some interface are to be modifed:
Declare Function CopyEnhMetaFile Lib "gdi32" Alias "CopyEnhMetaFileA" (ByVal hemfSrc As IntPtr, ByVal lpszFile As String) As IntPtr
Declare Function DeleteEnhMetaFile Lib "gdi32" (ByVal hemf As IntPtr) As Integer
Private Declare Function GdipEmfToWmfBits Lib "gdiplus.dll" (ByVal hEmf As IntPtr, ByVal bufferSize As UInteger, ByVal buffer() As Byte, ByVal mappingMode As Integer, ByVal flags As EmfToWmfBitsFlags) As UInteger
So i have the following code
Imports System.Diagnostics
Imports System.IO
Imports System.Runtime.InteropServices
Public Class Form1
<StructLayout(LayoutKind.Sequential)> _
Structure OSVERSIONINFO
Dim dwOSVersionInfoSize As Integer
Dim dwMajorVersion As Integer
Dim dwMinorVersion As Integer
Dim dwBuildNumber As Integer
Dim dwPlatformId As Integer
<MarshalAs(UnmanagedType.ByValTStr, SizeConst:=128), VBFixedString(128)> Dim szCSDVersion As String
End Structure
<StructLayout(LayoutKind.Sequential)> _
Structure MEMORY_BASIC_INFORMATION
Dim BaseAddress As Integer
Dim AllocationBase As Integer
Dim AllocationProtect As Integer
Dim RegionSize As Integer
Dim State As Integer
Dim Protect As Integer
Dim lType As Integer
End Structure
<StructLayout(LayoutKind.Sequential)> _
Structure SYSTEM_INFO ' 36 Bytes
Dim dwOemID As Integer
Dim dwPageSize As Integer
Dim lpMinimumApplicationAddress As Integer
Dim lpMaximumApplicationAddress As Integer
Dim dwActiveProcessorMask As Integer
Dim dwNumberOrfProcessors As Integer
Dim dwProcessorType As Integer
Dim dwAllocationGranularity As Integer
Dim wProcessorLevel As Short
Dim wProcessorRevision As Short
End Structure
Private Declare Function GetVersionEx Lib "kernel32" Alias "GetVersionExA" (ByRef LpVersionInformation As OSVERSIONINFO) As Integer
Private Declare Function VirtualQueryEx Lib "kernel32.dll" (ByVal hProcess As IntPtr, ByVal lpAddress As UInteger, ByRef lpBuffer As MEMORY_BASIC_INFORMATION, ByVal dwLength As Integer) As Integer
Private Declare Sub GetSystemInfo Lib "kernel32" (ByRef lpSystemInfo As SYSTEM_INFO)
Private Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Integer, ByVal blnheritHandle As Integer, ByVal dwAppProcessId As Integer) As Integer
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Integer) As Integer
Private Declare Function ReadProcessMemory Lib "kernel32" (ByVal hProcess As Integer, ByRef lpBaseAddress As Integer, ByRef lpBuffer As Long, ByVal nSize As Integer, ByRef lpNumberOfBytesWritten As Integer) As Integer
Private Declare Function WriteProcessMemory Lib "kernel32" (ByVal hProcess As Integer, ByRef lpBaseAddress As Integer, ByRef lpBuffer As String, ByVal nSize As Integer, ByRef lpNumberOfBytesWritten As Integer) As Integer
Private Declare Function GetWindowThreadProcessId Lib "user32" (ByVal hWnd As Integer, ByRef lpdwProcessId As Integer) As Integer
Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As Integer, ByVal lpWindowName As Integer) As Integer
Private Declare Function GetParent Lib "user32" (ByVal hWnd As Integer) As Integer
Private Declare Function GetWindow Lib "user32" (ByVal hWnd As Integer, ByVal wCmd As Integer) As Integer
Private Const PROCESS_VM_READ = (&H10)
Private Const PROCESS_VM_OPERATION = (&H8)
Private Const PROCESS_QUERY_INFORMATION = (&H400)
Public Const PROCESS_READ_WRITE_QUERY = PROCESS_VM_READ + PROCESS_VM_OPERATION + PROCESS_QUERY_INFORMATION
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim pid As Integer, hProcess As Integer
Dim lpMem As Integer, ret As DialogResult, lLenMBI As Integer
Dim lWritten As Integer
Dim sBuffer As String
Dim sSearchString As String = "", sReplaceString As String = ""
Dim si As SYSTEM_INFO
Dim mbi As MEMORY_BASIC_INFORMATION
For Each p As Process In Process.GetProcesses
If p.ProcessName = "notepad" Then
pid = p.Id
End If
Next
hProcess = OpenProcess(PROCESS_READ_WRITE_QUERY, False, pid)
lLenMBI = Len(mbi)
'Determine applications memory addresses range
GetSystemInfo(si)
lpMem = si.lpMinimumApplicationAddress
Do While lpMem < si.lpMaximumApplicationAddress
mbi.RegionSize = 0
ret = VirtualQueryEx(hProcess, lpMem, mbi, lLenMBI)
If ret = lLenMBI Then
If ((mbi.lType = &H20000) And (mbi.State = &H1000)) Then
If mbi.RegionSize > 0 Then
Dim stringinmemory As Long
sBuffer = mbi.RegionSize
ReadProcessMemory(hProcess, mbi.BaseAddress, stringinmemory, mbi.RegionSize, lWritten)
Debug.WriteLine(sBuffer)
End If
End If
lpMem = mbi.BaseAddress + mbi.RegionSize
Else
Exit Do
End If
Loop
CloseHandle(hProcess)
End Sub
End Class
And it should read all notepad memory (step by step like). I get no errors when i run it , but it returns
4096
4096
4096
8192
90112
4096
344064
131072
8192
45056
172032
4096
155648
4096
This code works well in VB6, but i converted it to VB.NET.
What am I doing wrong ? Can you help me please ?
Thanks in advance.
Nicu
You are printing the value of sBuffer which is an integer which explains the results you are seeing. Besides, sBuffer does not contain the data which is read from memory. I think your lpBuffer parameter (and also stringinmemory as well) should not be a Long but instead be an Byte array. Something like this:
Const PROCESS_WM_READ As Integer = &H10
<DllImport("kernel32.dll")> _
Public Shared Function OpenProcess(dwDesiredAccess As Integer, bInheritHandle As Boolean, dwProcessId As Integer) As IntPtr
End Function
<DllImport("kernel32.dll")> _
Public Shared Function ReadProcessMemory(hProcess As Integer, lpBaseAddress As Integer, lpBuffer As Byte(), dwSize As Integer, ByRef lpNumberOfBytesRead As Integer) As Boolean
End Function
Public Shared Sub Main()
Dim notepadProcess As Process = Process.GetProcessesByName("notepad")(0)
Dim processHandle As IntPtr = OpenProcess(PROCESS_WM_READ, False, notepadProcess.Id)
Dim bytesRead As Integer = 0
Dim buffer As Byte() = New Byte(23) {}
'The address in this line is hard-coded. Use whatever is appropriate for your situation.
ReadProcessMemory(CInt(processHandle), &H36B9D0, buffer, buffer.Length, bytesRead)
Console.WriteLine(Encoding.Unicode.GetString(buffer))
Console.ReadLine()
End Sub
OK, this problem has been bugging me for a long time.
I have the code for the service which communicates a string to the client via PostMessage:
Public Sub SendToClient(msgs As String, types As Integer, hwnd As Long)
postMessage(hwnd, 0, Nothing, msgs)
End Sub
Then I have the client that receives the string:
Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
If (m.Msg = 0) Then
Dim a as string
a = Marshal.PtrToStringAuto(m.LParam)
end if
MyBase.WndProc(m)
End Sub
However, the client sends an error, or some jumble of binary data or even just a blank string sometimes. By the way, the m.LParam is a number.
Can someone tell me what is the right way to send/receive strings via postmessage.
I do it like this:
Public Sub SendMessageToApp(ByVal NombreVentana As String, ByVal Mensaje As String, ByVal sender As Form)
Dim hWnd As IntPtr
Dim mCopyData As COPYDATASTRUCT
hWnd = CType(FindWindow(Nothing, NombreVentana), IntPtr)
Dim message As New System.Text.StringBuilder
If (CInt(hWnd) <> 0) Then
message.Append(Mensaje)
Dim pCopyData As IntPtr = Marshal.AllocHGlobal(message.Length() + 40)
mCopyData.lpData = Marshal.StringToHGlobalAnsi(message.ToString)
mCopyData.cbData = message.Length
mCopyData.dwData = CType(_messageID, IntPtr)
Marshal.StructureToPtr(mCopyData, pCopyData, False)
SendMessage(hWnd, WM_COPYDATA, CInt(sender.Handle), pCopyData)
Marshal.FreeHGlobal(mCopyData.lpData)
Marshal.FreeHGlobal(pCopyData)
End If
End Sub
Receiver window:
Declarations and definitions:
Const WM_COPYDATA As Integer = 74
Const SIG_LENGTH As Integer = 36
Const MAX_COPY_LENGTH As Integer = 128
Const SigConnect As String = "F7B82657-BD18-4ee6-B182-78721293821C"
Dim CDCount As Integer
Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" _
(ByVal lpClassName As String, ByVal lpWindowName As String) As Integer
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" _
(ByVal hwnd As IntPtr, ByVal wMsg As Integer, ByVal wParam As Integer, _
ByVal lParam As IntPtr) As Integer
Dim hWndSender As Integer
Private Const _messageID As Integer = 10
'Estructura obligatoria para poder utilizar el API CopyData
<StructLayout(LayoutKind.Sequential)> _
Private Structure COPYDATASTRUCT
Public dwData As IntPtr
Public cbData As Integer
Public lpData As IntPtr
End Structure
Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
If m.Msg = WM_COPYDATA Then
Dim Estructura As COPYDATASTRUCT
Dim tipo As Type = Estructura.GetType
Dim message As String
Estructura = CType(m.GetLParam(GetType(COPYDATASTRUCT)), COPYDATASTRUCT)
'Here you get the message
message = Marshal.PtrToStringAnsi(Estructura.lpData, Estructura.cbData)
End If
Edit: Fixed, I created a compatibleDC for the graphics object, and a handle for the bitmap (using b.gethbitmap), then used the SelectObject function inside GDI to select those two, and used the compatibleDC instead of hDc in the BitBlt function
I've been trying to draw a bitmap to the screen (device 0), however I have encountered a problem copying the graphics using BitBlt.
Initially, I was drawing directly to the desktop using SetPixel (gdi32), but it was slow, so now I am setting the pixels of a bitmap object and then creating graphics from that object, and copying the hdc of the graphics to the screen.
My guess is that I am adding the HDC of the graphics object to an intptr, which essentially gives me the HDC of the container of the graphics object, which is not what I need. However even so, I have not found any information on how I could copy a bitmap to a device other than using BitBlt.
This is my current code (Windows forms app, textbox, button) The textbox is the device to copy to, and the button starts it. For testing purposes, set the textbox text to 0, and press the button. You should see a black box (50x50px) in the top left corner of your screen. The colour should be blue if it is working correctly:
Public Class Form1
Declare Function GetDC Lib "user32.dll" (ByVal hwnd As Int32) As Int32
Declare Function ReleaseDC Lib "user32.dll" (ByVal hwnd As Int32, ByVal hdc As Int32) As Int32
Declare Function SetPixel Lib "gdi32.dll" (ByVal hdc As Integer, ByVal x As Integer, ByVal y As Integer, ByVal crColor As Integer) As Integer
Declare Function BitBlt Lib "gdi32.dll" (ByVal hdcDest As IntPtr, ByVal nXDest As Integer, ByVal nYDest As Integer, ByVal nWidth As Integer, ByVal nHeight As Integer, ByVal hdcSrc As IntPtr, ByVal nXSrc As Integer, ByVal nYSrc As Integer, ByVal dwRop As Int32) As Boolean
Declare Function CreateCompatibleBitmap Lib "gdi32.dll" (ByVal hdc As IntPtr, ByVal nWidth As Integer, ByVal nHeight As Integer) As IntPtr
Declare Function CreateCompatibleDC Lib "gdi32.dll" (ByVal hdc As IntPtr) As IntPtr
Dim x As Integer
Sub setpx(ByVal location As Point, ByVal color As Color)
b.SetPixel(location.X, location.Y, color)
End Sub
Sub drawrectangle(ByVal device As Integer, ByVal location As Point, ByVal size As Point, ByVal color As Color)
b = New Bitmap(size.X, size.Y)
For i = location.X To size.X - 1
For z = location.Y To size.Y - 1
setpx(New Point(i, z), color)
Next
Next
g = Graphics.FromImage(b)
Dim hDc As IntPtr = g.GetHdc
BitBlt(GetDC(device), location.X, location.Y, size.X, size.Y, hDc, location.X, location.Y, 13369376)
ReleaseDC(device, GetDC(device))
End Sub
Dim b As Bitmap
Dim g As Graphics
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Buttnon1.Click
Dim r As New Random
Dim timestart As Integer = Now.TimeOfDay.TotalMilliseconds
drawrectangle(TextBox1.Text, New Point(1, 1), New Point(50, 50), Color.Blue)
MsgBox(Now.TimeOfDay.TotalMilliseconds - timestart)
End Sub
End Class
The way it works is it calls the function setpx, given a location and color from within a loop iterating through all of the pixels in a box (50x50 in my code). The setpx function will then call the setpixel function on a bitmap b. This part is working fine.
Next, it will define a graphics object g from the bitmap, and I use BitBlt to copy g's hdc (g.gethdc) to the screen. This is not working correctly, is this the correct way of doing this?
You are passing Textbox1.text as a device descriptor, that won't work...You want textbox1.hwnd