2009/09/16

網路關機

我找到方法了

在要進行關機的電腦上,按下開始-執行,然後在執行對話盒輸入gpedit.msc再按下確定
群組原則視窗出現後,找到本機電腦原則-電腦設定-Windows設定這個項目,然後依序展開安全性設定-本機原則,最後在使用者權限指派上按一下滑鼠左鍵。
在右邊窗格找到從遠端榭統強制關機,然後在這個項目上按一下滑鼠右鍵,從選單中選內容
對話盒出現後,裡面只有Administrator這個使用者,在新增使用者或群組上按一下滑鼠左鍵,準備將Guest使用者新增進來
選擇使用或群組對話盒出現後,在下方的進階上按一下滑鼠左鍵。
接著在對話盒按下立即尋找,下方的方塊就會顯示所有的使用者,在
Guest使用者上按一下滑鼠左鍵,然後按下確定
現在對話盒中就會出現Guest使用者,按下確定,回到上個對話盒再按一次確定
現在到採取遙控的電腦上,建立捷徑圖示來進行遠端關機,先在桌面上空白的地方按一下滑鼠右鍵,依序點選新增-捷徑
建立捷徑對話盒出現後,輸入shutdown -s -m 電腦名稱或ip -t 3格式的指令,再按下一步
最後設定捷徑的名稱,如遠端關機,再按下完成,以後只要在建立好的捷徑圖示上連續按兩下滑鼠左鍵,就可以讓家裡的電腦關機了。

2009/05/07

VB6 二進位資料 轉 數值

VB6 二進位資料 轉 數值
當我們有二進位資料 如 &H3483126f
如何才能轉成 2.44141e-7 數值
使用 CopyMemory 函數 參考如下

範例:

Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (hpvDest As Any, hpvSource As Any, ByVal cbCopy As Long)

Dim lVar As Long
Dim iLoop As Integer
Dim bArray(1 To 4) As Byte

lVar = &H40030201

CopyMemory bArray(1), lVar, 4
For iLoop = 1 To 4
   If bArray(iLoop) And &HF0 Then
      Debug.Print Hex$(bArray(iLoop));
   Else
      Debug.Print "0" & Hex$(bArray(iLoop));
   End If
Next

這段程式把 lVar 的值原封不動地複製到 bArray 之中,由於 lVar 的大小為 4 個位元組,因此我們設定 bArray 的元素個數為 4 個。Array 在下下期電子期將會被介紹到,在這�暫時只要知道數字陣列的元素在記憶體中是連續的就好了。用白話來解釋 CopyMemory bArray(1), lVar, 4 這行程式碼是:
將由 lVar 變數起始的 4 個位元組複製到由 bArray(1) 起始 4 位元組大小的位元區塊。

由 lVar = &H40030201 我們知道了 lVar 的內容。最後一部分的 For…Next 是將 bArray 中複製的內容印在即時視窗中以便與 lVar 的內容對照。如果您把程式放到 VB 中執行,您將會得到結果:01020340!

咦?lVar 的內容為 40030201 呀,怎麼我們得到 01020340 呢?這到底是怎麼一回事?

這個問題牽涉到電腦二進位資料儲存的順序,叫做 Little Endian。簡單的說 little endian 是指資料儲存時的順序將是低順位的位元儲存在較低位址的記憶體中,當 CPU 由記憶體中讀取資料時,由較低的位址開始讀起。因此在上例中當 lVar 引數傳 CopyMemory 中時,所傳入的記憶體位址是位元值 01 的最低順位位元,之後由低往高讀上去,所以在 bArray 中的元素值才會是顛倒的。

參考處:
http://tlcheng.twbbs.org/Paper/Variant/Variant.htm

http://mychannel.pchome.com.tw/channel/class/show_preview.php3/?d=2002-07-18&enname=winapi4vber&t=.htm&fn=main&view=1

2009/01/08

VB6 動態新增控制項物件

【方法一】增加動態物件陣列

新增方法:
Laod ObjectArray(Index),如 Load Text1(10)。

    《注意事項》
        1.最初物件陣列必須先存在,如 Text1(0)。
        2.引數Index不可以重複。
    優點:
        Load 新增的控制項物件會繼承(Inheritance)原先控制項物件的屬性設定,
        如 Text1(10). MultiLine = True 會自動設定,這個屬性在執行時期無法動態更改。

刪除方法:
Unload ObjectArray(Index) ,如 Unload Text1(10)。

事件觸發:
Private Sub Text1_Change(Index As Integer)
    Select Case Index
    Case 1
        '..... 觸發的控制項
    End Select
End Sub


【方法二】控制項集合(Controls collection)

新增方法:
Set ControlRef=Controls.Add(ProgID,Name [,Container])

    說明:
        1.ProgID是指控制項的類別名稱,它是 Libraryname.controlname 的格式。
        2.Name 是您給控制項的名稱, (這就是控制項Name屬性所傳回名稱) 。
            Name 必需為唯一的(unique),假如在集合中有其它的控制項具有同樣
            的名稱,就會產生
            Error 727 "There is already a control with the name 'ctrlname'" 。
        3.Container 為選擇性參數,是一個對收納器控制項(如PictureBox 或
            是Frame控制項)的引用,如果沒有指定或為 NULL,預設值
            為Controls 集合物件所屬的收納器。
        4.ControlRef 為物件變數,是一個對該控制項的引用,透過此變數可
            使用控制項的屬性,方法及事件,由底下的程式碼您可以發現要在
            表單右下角,動態新增一個控制項,是非常容易的一件事。

範例:
Private Sub Command1_Click()
    Set textCtrl1 = Controls.Add("vb.textbox", "textCtrl1")
    textCtrl1.Text = "textCtrl1"
    textCtrl1.Visible = True
    Set textCtrl2 = Controls.Add("vb.textbox", "textCtrl2")
    textCtrl2.Top = 500
    textCtrl2.Text = "textCtrl2"
    textCtrl2.Visible = True
End Sub

優點:
無須最初物件陣列 textCtrl(0),便可以無中生有來動態新增控制項。


刪除方法:
Controls.Remove Control

範例:
Private Sub Command3_Click()
    UnLoadCtrl "textCtrl1"
End Sub

Private Sub UnLoadCtrl(ByVal ctrlName As String)
    Dim Ctrls As Control
    For Each Ctrls In Controls
        If Ctrls.Name = ctrlName Then Controls.Remove Ctrls
    Next
End Sub


    《注意事項》
        Controls.Remove Control 只能刪除Controls.Add 所建立之物件,不然會發生執行階段錯誤 729。

事件觸發:
使用到 WithEvents 變數可以讓您對它的事件作處理。
Option Explicit
'--- textCtrl 先設定 Events
Dim WithEvents textCtrl1 As TextBox
Dim WithEvents textCtrl2 As TextBox

Private Sub textCtrl1_Change()
    Me.Caption = "textCtrl1_Change"
End Sub
Private Sub textCtrl1_GotFocus()
    Me.Caption = "textCtrl1_GotFocus"
End Sub
Private Sub textCtrl2_Change()
    Me.Caption = "textCtrl2_Change"
End Sub
Private Sub textCtrl2_GotFocus()
    Me.Caption = "textCtrl2_GotFocus"
End Sub

《問題》每一次新增控制項就要先設定 WithEvents,使用上非常不方便。

【以下範例可改良上面 WithEvents 的不方便,使用 SubClassing 方法】
Command2_Click 動態新增物件的手法

' 於表單
Option Explicit
'--- textCtrl 設定 Events
Dim WithEvents textCtrl1 As TextBox
Dim WithEvents textCtrl2 As TextBox

Private Sub Command1_Click()
    Set textCtrl1 = Controls.Add("vb.textbox", "textCtrl1")
    textCtrl1.Text = "textCtrl1"
    textCtrl1.Visible = True
    Set textCtrl2 = Controls.Add("vb.textbox", "textCtrl2")
    textCtrl2.Top = 500
    textCtrl2.Text = "textCtrl2"
    textCtrl2.Visible = True
End Sub

'----- 新增10個 TextBox 控制項 ( Controls.Add )
Private Sub Command2_Click()
    Dim txtArray As Object
    Dim Index As Long
    Dim str As String
    '新增10個 TextBox
    Index = 10
    ReDim CtrlhWnd(Index - 1)
    For Index = 0 To Index - 1
        str = "txtArray" & Index
        Set txtArray = Controls.Add("vb.textbox", str)
        With txtArray
            .Top = Index * 300
            .Left = 1300
            .Height = 280
            .Width = 1000
            .Text = str
            .Visible = True
            CtrlhWnd(Index) = .hwnd
        End With
    Next
    '--- txtArray 設定 Events
    MeProc = SetWindowLong(Me.hwnd, GWL_WNDPROC, AddressOf WindowProc)
End Sub

Private Sub Command3_Click()
    UnLoadCtrl "textCtrl1"
End Sub
Private Sub UnLoadCtrl(ByVal ctrlName As String)
    Dim Ctrls As Control
    For Each Ctrls In Controls
        If Ctrls.Name = ctrlName Then Controls.Remove Ctrls
    Next
End Sub

Private Sub Form_Unload(Cancel As Integer)
    SetWindowLong Me.hwnd, GWL_WNDPROC, MeProc
End Sub

'---------- ALL Events()
Private Sub textCtrl1_Change()
    Me.Caption = "textCtrl1_Change"
End Sub
Private Sub textCtrl1_GotFocus()
    Me.Caption = "textCtrl1_GotFocus"
End Sub

Private Sub textCtrl2_Change()
    Me.Caption = "textCtrl2_Change"
End Sub
Private Sub textCtrl2_GotFocus()
    Me.Caption = "textCtrl2_GotFocus"
End Sub

Public Sub txtArray_Change(Index As Integer)
    Me.Caption = "txtArray" & Index & "_Change"
End Sub
Public Sub txtArray_GotFocus(Index As Integer)
    Me.Caption = "txtArray" & Index & "_GotFocus"
End Sub


' 於模組
Option Explicit
Public Type LongToByte
    B0 As Byte
    B1 As Byte
    B2 As Byte
    B3 As Byte
End Type
Public bLong As LongToByte
Public Const WM_COMMAND = &H111
Public Const GWL_WNDPROC = (-4)
Public MeProc As Long
Public CtrlhWnd() As Long
Public Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Public Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal hwnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Public Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)

Public Function WindowProc(ByVal hwnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
    Select Case uMsg
    Case WM_COMMAND
        Dim Index As Integer
        For Index = 0 To UBound(CtrlhWnd)
            If lParam = CtrlhWnd(Index) Then
                CopyMemory bLong, wParam, 4
                Select Case bLong.B3
                Case &H3
                    Form1.txtArray_Change (Index)
                Case &H1
                    Form1.txtArray_GotFocus (Index)
                End Select
            End If
        Next
    End Select
    WindowProc = CallWindowProc(MeProc, hwnd, uMsg, wParam, lParam)
End Function