Just seen some really neat code for doing this at: http://addressof.com/blog/articles/232.aspx
I've also put a copy down below of the bit I used. I modified Cory Smiths code a little, so you don't have to remember to handle the resize event (a maximise or minimise for some reason renables the close button). On my modification I automatically add a handler for this in the Class CloseButton.
Public Class CloseButton
Private Declare Function GetSystemMenu Lib "user32" (ByVal hwnd As Integer, ByVal revert As Integer) As Integer
Private Declare Function EnableMenuItem Lib "user32" (ByVal menu As Integer, ByVal ideEnableItem As Integer, ByVal enable As Integer) As Integer
Private Const SC_CLOSE As Integer = &HF060
Private Const MF_BYCOMMAND As Integer = &H0
Private Const MF_GRAYED As Integer = &H1
Private Const MF_ENABLED As Integer = &H0
Private Sub New()
End Sub
Public Shared Sub Disable(ByVal sender As System.Object, ByVal e As System.EventArgs)
' The return value specifies the previous state of the menu item (it is either
' MF_ENABLED or MF_GRAYED). 0xFFFFFFFF indicates that the menu item does not exist.
Dim frm1 As Form
frm1 = sender
Select Case EnableMenuItem(GetSystemMenu(frm1.Handle.ToInt32, 0), SC_CLOSE, MF_BYCOMMAND Or MF_GRAYED)
Case MF_ENABLED
Case MF_GRAYED
Case &HFFFFFFFF
Throw New Exception("The Close menu item does not exist.")
Case Else
End Select
End Sub
Public Shared Sub Disable(ByVal form As System.Windows.Forms.Form)
' The return value specifies the previous state of the menu item (it is either
' MF_ENABLED or MF_GRAYED). 0xFFFFFFFF indicates that the menu item does not exist.
Select Case EnableMenuItem(GetSystemMenu(form.Handle.ToInt32, 0), SC_CLOSE, MF_BYCOMMAND Or MF_GRAYED)
Case MF_ENABLED
Case MF_GRAYED
Case &HFFFFFFFF
Throw New Exception("The Close menu item does not exist.")
Case Else
End Select
AddHandler form.Resize, AddressOf CloseButton.Disable
End Sub
End Class
FAO Cory Smith, if you don't want your code on here contact me and I'll remove it.