2012年11月27日 星期二

[學習 ] 列舉表單上所有的控制項 列舉開啟的所有表單

當想一次完成某些控制項的(屬性)設定時。
        For Each Control As Windows.Forms.Control In Me.Controls
            If Control.GetType Is GetType(Button) Then
                Control.Enabled = False
                Control.Width = 200
            End If
        Next

        For Each Control As Windows.Forms.Control In Me.Controls
            If Control.GetType Is GetType(TextBox) Then
                Control.Enabled = False
                Control.Width = 200
            End If
        Next
,etc...

當想取得目前程式中所有被開啟的表單集合時。
        For Each frm As Form In My.Application.OpenForms
            MsgBox(frm.Name & "," & frm.Text)
        Next

之後就可以做你想做的運用了...
存取每個表單上的全域物件(或變數)。
ex:
if frm.Name = "form1" then .....
,etc...

備註:
如果某Control是停駐於另一個Control下
則用此方法會找不到
ex:TextBox1 停駐於 GroupBox1 下...
此時的方法只會顯示(查詢到) GroupBox
可參考 方法 或 更好的方法(待查)
[ASP.NET] 透析FindControl

參考:
[技巧] Controls.Find - 驗證篇

List Of ALL Controls In PROJECT - VB.Net
How to find all child controls from a starting control or form
Foreach Control in form, all the TextBoxes
How to recursively get all controls on a form in C#
How to get ALL child controls of a Windows Forms form
Foreach Every Control on all forms

[技巧] ReportViewer 超連結 Hyperlink 開啟本機檔案

Get Selected Value From ReportViewer via Hyperlink

CrystalReport 可直接在公式呼叫外部程式並傳入參數 或 直接開啟檔案 PDF WORD,etc...
formula = "C:\DAYLIGO\TEST\DayActivateFormWinApp.exe 21 " & LEFT(CSTR({RY010採購合同資料表.批號}),1)  & ""

ReportViewer 無法直接在公式呼叫外部程式 或 開啟檔案 PDF WORD,etc...
僅能超連結URL的網頁,所連結網頁會 GET/POST 接收參數!

或許 ReportViewer 有這樣的功能也說不定... 網路上也找的到相關的需求,但沒有解答!

解決方法:
    Private Sub ReportViewer1_Hyperlink(ByVal sender As System.Object, ByVal e As Microsoft.Reporting.WinForms.HyperlinkEventArgs) Handles ReportViewer1.Hyperlink
        '法一
        Dim aa As String = e.Hyperlink
        aa = aa.Replace("http://", "")
        aa = aa.Replace("/", " ")
        Shell("C:\Dayligo\TEST\DayActivateFormWinApp.exe " & aa, AppWinStyle.NormalFocus)
        'MsgBox(e.Hyperlink)
        e.Cancel = True

        '法二

        Dim bb As String = e.Hyperlink
        bb = bb.Replace("%20", " ")
        bb = bb.Replace("file:///", "")
        'MsgBox(e.Hyperlink)
        'MsgBox(bb)
        Shell(bb, AppWinStyle.NormalFocus)

        e.Cancel = True
    End Sub

'法一
在 report1.rdlc 將表格設定導覽,並指定到URL   ="http://19/" & Fields!sdid.Value
在 reporviewer1 運用 Hyperlink 事件,並取出 link 參數。
並在程式中解析~ 取出所要的參數。
19表示我要呼叫哪支程式(表單Form) 並傳入參數 sdid.Value

注意:
設定 enablehyperlinks = true
http:// <-- 這樣不會觸發連結事件
http://1/ <-- 這樣才會觸發連結事件



'法二
跳至URL:
="C:\Dayligo\TEST\DayActivateFormWinApp.exe 19 " & Fields!sdid.Value

開發工具:
VS2008
Framework3.5

參考:
如何获取ReportViewer呈现的报表中某单元格的值?
'Jump To' action with relative hyperlink
Hyperlink to a local file doesn't work
在ReportViewer中使用超链接(HyperLink)
啟動應用程式並且傳入參數

備註:
A組件下,某個視窗(水晶報表)
透過報表某欄位hyperlink開啟本地檔案DayActivateFormWinApp.exe (並且傳參數給本地檔案)
透過DayActivateFormWinApp.exe及接收的參數,再來呼叫A組件下的某支副程式
透過此支程式來呼叫B組件下,某個視窗(EX:個人資料檔案!!)
B組件依接到的參數顯示資料

2012年11月26日 星期一

[技巧] 判斷是否已開啟視窗

法一 - A、
只能在 父MDI [MAIN_ligoHRsys] 下運作! 當嵌入其它組件時,無法在其下 父MDI 下運算!
        '若表單已存在 則讓他為主要顯示表單
        If l_Frm IsNot Nothing Then

            For i As Integer = 0 To MAIN_ligoHRsys.FindForm().MdiChildren.Length - 1
                If frmText.Equals(MAIN_ligoHRsys.FindForm().MdiChildren(i).Text) Then
                    MAIN_ligoHRsys.FindForm().MdiChildren(i).Tag = 4
                    MAIN_ligoHRsys.FindForm().MdiChildren(i).Activate()
                    DirectCast(MAIN_ligoHRsys.FindForm().MdiChildren(i), Object).MyDataRequery(Nothing)
                End If
            Next
        End If


法一 - B、
當嵌入在任何組件時 在其 父MDI 下運作,必使用 Me.Parent 方可執行!
        '若表單已存在 則讓他為主要顯示表單
        If l_Frm IsNot Nothing Then

            For i As Integer = 0 To Me.Parent.FindForm().MdiChildren.Length - 1
                If frmText.Equals(Me.Parent.FindForm.MdiChildren(i).Text) Then
                    Me.Parent.FindForm.MdiChildren(i).Activate()
                    Me.Parent.FindForm.MdiChildren(i).Tag = 1
                    DirectCast(Me.Parent.FindForm().MdiChildren(i), Object).MyDataRequery(Nothing)
                End If
            Next
        End If


法二、
If My.Application.OpenForms.Item("FormName") IsNot Nothing Then
     'do something here 已經打開
Else
     'do something here 還沒打開
End If


法三、[C#]
            if (Application.OpenForms.OfType<frm力高裝箱明細列印作業>().Count() == 1)
                Application.OpenForms.OfType<frm力高裝箱明細列印作業>().First().Activate();
            else
            {
                frm裝箱明細列印作業 frm = new frm裝箱明細列印作業();
                frm.MdiParent = this.MdiParent;
                frm.Show();
            }   


參考:
[MSDN]Form.ActiveMdiChild 屬性
[MSDN]My.Application.OpenForms 屬性
VB.NET判断一个窗口是否打开的代码
[C#.NET] 如何 使用 WinForm 關閉 視窗 事件
C# WinForm 只允许运行一个实例 ,如果有就激活到前段
WinFrom 判断窗体是否已存在

2012年11月20日 星期二

[學習] 多使用者 處理 同一筆資料 防止 race condition

系統架構
User1(程式)
                            <--------->       SV1(WebService)       <--------->       SV2(DataBase)
User2(程式)
       .
       .
       .
UserN(程式)


 (強碰問題~ 幾乎很少發生!!)
1.(程式-產生序號 Fetch From DB & +1) ex: sn+=1
當多個user同時處理同一筆record時~~
在不違反商業邏輯狀態下,直接覆蓋(update)前者的資料~~
每個record都會有記錄欄位,記錄修改者是誰~~

2.(程式-產生序號 Fetch From DB & +1) ex: sn+=1
在user1處理A-record時 不讓其它user同時處理A-record

user1(程式) 發出個訊息(參數) 給 SV1
其它user處理record時 並先與SV1判斷是否同record
若是 則告知其它user 目前不能用

-但會有網路斷線問題~~
-故需要一個機制~~
-那便是一個處理record的時間~~
-並在n分鐘內不讓其它使用者處理同一筆record~~

時間可存在 DataBase(同一筆record的欄位) 或 SV1

參考:
用 SELECT ... FOR UPDATE 避免 Race condition
数据库插入,多人操作,如何能做到绝对不重复插入?
select 後 insert
競爭危害

2012年11月18日 星期日

[除錯] 轉換 expression 到資料型別 smalldatetime 時發生算術溢位錯誤


---Error Message----
1.INSERT INTO SQL SERVER時引發錯誤,SQL資料類型 smalldatetime
將 varchar 資料類型轉換成 smalldatetime 資料類型時,產生超出範圍的值

2.
轉換 expression 到資料型別 smalldatetime 時發生算術溢位錯誤
轉換 nvarchar 到資料型別 smalldatetime 時發生算術溢位錯誤
,etc...




資料庫欄位型態為 datetime or smalldatetime
程式 insert 時,必須注意日期規則是否溢位

Ex:
一月份最大日期為31日
此時 insert 32 便會 error


解決辦法(1)--  
其實用 ISDate() 最準 
接受輸入格式 
(1)12-24 (自動加入今年)
(2)12-01-01 ,  2013-1-1,
(3)2011/1/1 ,  2012/01/12
(4)12/1-01 


在 insert 前判別規則
ex: 正規化表示法
If Not Regex.IsMatch(C.Text.Trim, "^((19|20)?[0-9]{2}[- /.](0?[1-9]|1[012])[- /.](0?[1-9]|[12][0-9]|3[01]))*$") Then
   'do something
End



解決辦法(2)--
將資料庫 欄位型態 改為 varchar / nvarchar


溢位是因為期中有NULL值或空白值 

解決辦法(3)--
WHERE下條件
where date <> "" and date is not null 或是 where isdate(date)

NOTE:
一、IsDate() 有效日期的範圍是介於西元 100 年 1 月 1 日與西元 9999 年 12 月 31 日之間;其有效範圍會因作業系統而有所差異。

二、
smalldatetime 有效時間範圍 1900/1/1~2079/6/6
datetime 有效時間範圍 1753/1/1~9999/12/31
所以如果不用到太遠的日期範圍,就會使用smalldatetime。
更關鍵的差別,smalldatetime只精準到分,而datetime可精準到3.33毫秒。





參考1
參考2
參考3




[學習] Directory.GetCurrentDirectory 和 Application.StartupPath 區別

Imports System.IO

—————————————————————————————
StartupPath 程式執行後,路徑位置不因外在因素而變。
GetCurrentDirectory 程式執行後,路徑位置會因外在因素而變。
—————————————————————————————

獲取文件路徑定義
Application.StartupPath——獲取啟動了應用程序的可執行文件的路徑,不包括可執行文件的名稱。
Environment.CurrentDirectory——獲取和設置當前目錄(即該進程從中啟動的目錄)的完全限定路徑。
Application.ExecutablePath——獲取啟動了應用程序的可執行文件的路徑,包括可執行文件的名稱。
Directory.GetCurrentDirectory()——獲取應用程序的當前工作目錄。
Directory.GetCurrentDirectory()——程序文件自身的路徑。


GetCurrentDirectory 會受 OpenFileDialog(SaveFileDialog) 的影響,而改變路徑位置。
假如有兩個程式 C:/A/a.exe 和 C:/B/b.exe
當在 a.exe 中啟動 b.exe,System.Diagnostics.Process.Start(@"C:/B/b.exe")
此時 b.exe 中的 Directory.GetCurrentDirectory() 返回值為 “C:/A”
Application.StartupPath 值為“C:/B”

如果直接在 C:/B/ 中啟動 b.exe,那麼兩個值就會一樣,都為“C:/B”
這就是 Directory.GetCurrentDirectory 和 Application.StartupPath 的區別

Application.StartupPath 是程序的啟動目錄,這個在程序運行以後,就不會改變了。
Directory.GetCurrentDirectory() 是"當前目錄",是可以在程序運行時候改變的 ,
用Directory.SetCurrentDirectory() 就可以改變。
Directory.GetCurrentDirectory() 初始值和 Application.StartupPath() 一樣。

參考:
[C#]使用 Path 類別取得檔案或目錄路徑資訊
File.Exists 方法
有关File.Exists(filename)的问题
c# 獲取相對路徑
取得目前執行程式的目錄

2012年11月13日 星期二

[除錯] 建立視窗控制代碼時發生錯誤 (下)

建立視窗控制代碼時發生錯誤 (上)

網路上這樣的發問訊息不多...
在(中文)資訊很少 也無解決方法...
有談論到的中文網站
 點我點我(1)
 點我點我(2) <<---- 有解決方法 但不是我要的!

(英文)資訊較多 卻苦無解決方法(讀者可以試試找英文的文件)...
[KeyWords]
Creating Window Handle
System.outOfMemoryException
System.NullReferenceException
MdiParent
FormWindowState.Maximized

有遇到相同原因的 或許可以試試
若剛好同樣的原因 那恭喜你 可以解決了

解決辦法

(1)

        p_mdi.MdiParent = Me
        p_mdi.WindowState = FormWindowState.Maximized
        p_mdi.Show()

改成
        p_mdi.Owner = Me
        p_mdi.WindowState = FormWindowState.Maximized
        p_mdi.Show()

這樣就不是MDI表單了~
但問題解決了~

(2)

p_mdi.WindowState = FormWindowState.Maximized

註解掉~ 並且不讓子表單在放大狀態運作~
這樣在畫面上會很怪 也很不符合使用邏輯~
但問題也解決了~

實際上可解決辦法

(1)
(Coding狀態) 將 [UI畫面] 拉大至可以將 [TextBox1] 容納~

(2)
將 btn[版面設置] 移至 [TextBox1] 後面~ 此時(Coding狀態) [TextBox1] 便落在 [UI畫面] 上~

(3)
將 [TextBox1] 位置 調置前面 使落在 [UI畫面] 上~

(4)
不管你用什麼辦法~ 
(刪除前面某個btn or others 讓 [TextBox1] 落在 [UI畫面] 上)
(刪除 [TextBox1])
, etc...

只要讓 [TextBox1] 在(Coding狀態) [UI畫面上] 便解決問題!
若是在程式執行時~ 才拉大UI畫面 一樣會出錯!


真正原因在於...............................................(研究中)

一、
我將專案每個表單內的程式全清空~ 僅保留空的程式!

EX: (表單 Class 原始)
Public Class MGMT_Personal
       'do something
End Class

UI設計畫面保留~
程式依然出錯~ 所以確定不是 Code 的問題!

二、
建立新的專案 測試MDI 也將 [TextBox1] (Codeing狀態)移出 [UI畫面] 外~
執行不會出錯 所以是原本專案上 拉UI時 未知的地方出錯~



----不無可能是程式碼某部份寫錯 for loop 之類的東西----

[除錯] 建立視窗控制代碼時發生錯誤 (上)

建立視窗控制代碼時發生錯誤 (下)

(1)開發環境 Development Environment
WinXP (32-bit x86) SP3
VS.NET 2008
.Net Framework 3.5

VB WinForm
MDI Form

(2)程式碼 Code
    '建立新的子表單
    Private Sub ShowMDIForm(ByVal p_mdi As Form)
        p_mdi.MdiParent = Me
        'p_mdi.Owner = Me
        p_mdi.WindowState = FormWindowState.Maximized
        p_mdi.Show()
    End Sub

    '檢查是否子表單已存在
    Function checkFormExist(ByVal FormText As String) As Boolean
        Dim bFound As Boolean = False
        For Each f As Form In Me.MdiChildren
            If f.Text.Equals(FormText) Then
                f.Activate()
                bFound = True
                Exit For
            End If
        Next
        Return bFound
    End Function

    '建立子表單
    Private Sub TreeView1_NodeMouseClick(ByVal sender As Object, ByVal e As System.Windows.Forms.TreeNodeMouseClickEventArgs) Handles TreeView1.NodeMouseClick
        Dim l_Frm As Form = New Form
        Select Case e.Node.Text
            Case "個資管理"
                l_Frm = New MGMT_Personal
            Case "薪資管理"
                l_Frm = New MGMT_Salary
            Case "任職管理"
                l_Frm = New MGMT_P
            Case "事項管理"
                l_Frm = New MGMT_ImptItem
        End Select

        '判斷存表單是否已存在 - 若否則開啟 New & Show
        If checkFormExist(l_Frm.Text) = False Then
            ShowMDIForm(l_Frm)
        End If

        '判斷存表單是否已存在 - 若是則開啟 Activate
        If l_Frm IsNot Nothing Then
            For i As Integer = 0 To Me.MdiChildren.Length - 1
                If e.Node.Text.Equals(Me.MdiChildren(i).Text) Then
                    Me.MdiChildren(i).Activate()
                    'Return
                End If
            Next
        End If
    End Sub

(3)參考畫面


(4)錯誤產生時間
當點選 "任職管理" 再點選其它 "表單選項" 便會發生 Error!

(5)參考辦法
疑難排解例外狀況:System.OutOfMemoryException


使用過多的 Managed 記憶體,通常是因為:
  • 將大量資料集讀入記憶體中。
  • 建立過多的快取項目。
  • 上傳或下載大型檔案。
  • 剖析檔案時,使用太多規則運算式 (Regular Expression) 或字串。
  • 檢視狀態過多。
  • 工作階段狀態中有過多資料,或工作階段過多。
在 COM 物件上叫用方法,而且這個 COM 物件會傳回包含安全陣列 (非固定大小的陣列) 的使用者定義型別時,便可能會擲回這個例外狀況,其中的訊息為:「存放裝置空間不足,無法完成此操作」。這是因為 .NET Framework 無法封送處理具有安全陣列型別的結構欄位。

(6)錯誤訊息
System.OutOfMemoryException 未處理
  Message="建立視窗控制代碼時發生錯誤。"
  Source="System.Windows.Forms"
  StackTrace:
       於 System.Windows.Forms.NativeWindow.CreateHandle(CreateParams cp)    於 System.Windows.Forms.Control.CreateHandle()    於 System.Windows.Forms.Form.CreateHandle()    於 System.Windows.Forms.Control.get_Handle()    於 System.Windows.Forms.Form.SetVisibleCore(Boolean value)    於 System.Windows.Forms.Control.Show()    於 eHRsys.MAIN_ligoHRsys.ShowMDIForm(Form p_mdi) 於 C:\Documents and Settings\Administrator\My Documents\Visual Studio 2008\eHRsys\eHRsys\MAIN_ligoHRsys.vb: 行 33    於 eHRsys.MAIN_ligoHRsys.TreeView1_NodeMouseClick(Object sender, TreeNodeMouseClickEventArgs e) 於 C:\Documents and Settings\Administrator\My Documents\Visual Studio 2008\eHRsys\eHRsys\MAIN_ligoHRsys.vb: 行 74    於 System.Windows.Forms.TreeView.OnNodeMouseClick(TreeNodeMouseClickEventArgs e)    於 System.Windows.Forms.TreeView.WmNotify(Message& m)    於 System.Windows.Forms.TreeView.WndProc(Message& m)    於 System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)    於 System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)    於 System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)    於 System.Windows.Forms.UnsafeNativeMethods.SendMessage(HandleRef hWnd, Int32 msg, IntPtr wParam, IntPtr lParam)    於 System.Windows.Forms.Control.SendMessage(Int32 msg, IntPtr wparam, IntPtr lparam)    於 System.Windows.Forms.Control.ReflectMessageInternal(IntPtr hWnd, Message& m)    於 System.Windows.Forms.Control.WmNotify(Message& m)    於 System.Windows.Forms.Control.WndProc(Message& m)    於 System.Windows.Forms.ScrollableControl.WndProc(Message& m)    於 System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)    於 System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)    於 System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)    於 System.Windows.Forms.UnsafeNativeMethods.CallWindowProc(IntPtr wndProc, IntPtr hWnd, Int32 msg, IntPtr wParam, IntPtr lParam)    於 System.Windows.Forms.NativeWindow.DefWndProc(Message& m)    於 System.Windows.Forms.Control.DefWndProc(Message& m)    於 System.Windows.Forms.TreeView.WmMouseDown(Message& m, MouseButtons button, Int32 clicks)    於 System.Windows.Forms.TreeView.WndProc(Message& m)    於 System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)    於 System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)    於 System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)    於 System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)    於 System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(Int32 dwComponentID, Int32 reason, Int32 pvLoopData)    於 System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)    於 System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)    於 System.Windows.Forms.Application.Run(ApplicationContext context)    於 Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.OnRun()    於 Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.DoApplicationModel()    於 Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.Run(String[] commandLine)    於 eHRsys.My.MyApplication.Main(String[] Args) 於 17d14f5c-a337-4978-8281-53493378c1071.vb: 行 81    於 System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args)    於 System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)    於 Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()    於 System.Threading.ThreadHelper.ThreadStart_Context(Object state)    於 System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)    於 System.Threading.ThreadHelper.ThreadStart()
  InnerException: System.NullReferenceException
       Message="並未將物件參考設定為物件的執行個體"
       Source="System.Windows.Forms"
       StackTrace:
            於 System.Windows.Forms.NativeWindow.WindowClass.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)    於 System.Windows.Forms.UnsafeNativeMethods.IntCreateWindowEx(Int32 dwExStyle, String lpszClassName, String lpszWindowName, Int32 style, Int32 x, Int32 y, Int32 width, Int32 height, HandleRef hWndParent, HandleRef hMenu, HandleRef hInst, Object pvParam)    於 System.Windows.Forms.UnsafeNativeMethods.CreateWindowEx(Int32 dwExStyle, String lpszClassName, String lpszWindowName, Int32 style, Int32 x, Int32 y, Int32 width, Int32 height, HandleRef hWndParent, HandleRef hMenu, HandleRef hInst, Object pvParam)    於 System.Windows.Forms.NativeWindow.CreateHandle(CreateParams cp)
       InnerException:

-------------------------------------------------------------------------

如需叫用 Just-In-Time (JIT) 偵錯的詳細資料,
請參閱本訊息結尾處 (而非這個對話方塊) 的資訊。

************** 例外狀況文字 **************
System.OutOfMemoryException: 建立視窗控制代碼時發生錯誤。 ---> System.NullReferenceException: 並未將物件參考設定為物件的執行個體
   於 System.Windows.Forms.NativeWindow.WindowClass.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
   於 System.Windows.Forms.UnsafeNativeMethods.IntCreateWindowEx(Int32 dwExStyle, String lpszClassName, String lpszWindowName, Int32 style, Int32 x, Int32 y, Int32 width, Int32 height, HandleRef hWndParent, HandleRef hMenu, HandleRef hInst, Object pvParam)
   於 System.Windows.Forms.UnsafeNativeMethods.CreateWindowEx(Int32 dwExStyle, String lpszClassName, String lpszWindowName, Int32 style, Int32 x, Int32 y, Int32 width, Int32 height, HandleRef hWndParent, HandleRef hMenu, HandleRef hInst, Object pvParam)
   於 System.Windows.Forms.NativeWindow.CreateHandle(CreateParams cp)
   --- 內部例外狀況堆疊追蹤的結尾 ---
   於 System.Windows.Forms.NativeWindow.CreateHandle(CreateParams cp)
   於 System.Windows.Forms.Control.CreateHandle()
   於 System.Windows.Forms.Form.CreateHandle()
   於 System.Windows.Forms.Control.get_Handle()
   於 System.Windows.Forms.Form.SetVisibleCore(Boolean value)
   於 System.Windows.Forms.Control.Show()
   於 eHRsys.MAIN_ligoHRsys.ShowMDIForm(Form p_mdi) 於 C:\Documents and Settings\Administrator\My Documents\Visual Studio 2008\Projects\eHRsys\eHRsys\MAIN_ligoHRsys.vb: 行 9
   於 eHRsys.MAIN_ligoHRsys.TreeView1_NodeMouseClick(Object sender, TreeNodeMouseClickEventArgs e) 於 C:\Documents and Settings\Administrator\My Documents\Visual Studio 2008\Projects\eHRsys\eHRsys\MAIN_ligoHRsys.vb: 行 55
   於 System.Windows.Forms.TreeView.OnNodeMouseClick(TreeNodeMouseClickEventArgs e)
   於 System.Windows.Forms.TreeView.WmNotify(Message& m)
   於 System.Windows.Forms.TreeView.WndProc(Message& m)
   於 System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
   於 System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
   於 System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)


************** 已載入的組件 **************
mscorlib
    組件版本: 2.0.0.0
    Win32 版本: 2.0.50727.3634 (GDR.050727-3600)
    程式碼基底: file:///C:/WINNT/Microsoft.NET/Framework/v2.0.50727/mscorlib.dll
----------------------------------------
eHRsys
    組件版本: 1.0.0.0
    Win32 版本: 1.0.0.0
    程式碼基底: file:///C:/Documents%20and%20Settings/Administrator/My%20Documents/Visual%20Studio%202008/Projects/eHRsys/eHRsys/bin/Debug/eHRsys.exe
----------------------------------------
Microsoft.VisualBasic
    組件版本: 8.0.0.0
    Win32 版本: 8.0.50727.3053 (netfxsp.050727-3000)
    程式碼基底: file:///C:/WINNT/assembly/GAC_MSIL/Microsoft.VisualBasic/8.0.0.0__b03f5f7f11d50a3a/Microsoft.VisualBasic.dll
----------------------------------------
System
    組件版本: 2.0.0.0
    Win32 版本: 2.0.50727.3634 (GDR.050727-3600)
    程式碼基底: file:///C:/WINNT/assembly/GAC_MSIL/System/2.0.0.0__b77a5c561934e089/System.dll
----------------------------------------
System.Windows.Forms
    組件版本: 2.0.0.0
    Win32 版本: 2.0.50727.3637 (GDR.050727-3600)
    程式碼基底: file:///C:/WINNT/assembly/GAC_MSIL/System.Windows.Forms/2.0.0.0__b77a5c561934e089/System.Windows.Forms.dll
----------------------------------------
System.Drawing
    組件版本: 2.0.0.0
    Win32 版本: 2.0.50727.3639 (GDR.050727-3600)
    程式碼基底: file:///C:/WINNT/assembly/GAC_MSIL/System.Drawing/2.0.0.0__b03f5f7f11d50a3a/System.Drawing.dll
----------------------------------------
System.Configuration
    組件版本: 2.0.0.0
    Win32 版本: 2.0.50727.3053 (netfxsp.050727-3000)
    程式碼基底: file:///C:/WINNT/assembly/GAC_MSIL/System.Configuration/2.0.0.0__b03f5f7f11d50a3a/System.Configuration.dll
----------------------------------------
System.Xml
    組件版本: 2.0.0.0
    Win32 版本: 2.0.50727.3082 (QFE.050727-3000)
    程式碼基底: file:///C:/WINNT/assembly/GAC_MSIL/System.Xml/2.0.0.0__b77a5c561934e089/System.Xml.dll
----------------------------------------
System.Runtime.Remoting
    組件版本: 2.0.0.0
    Win32 版本: 2.0.50727.3053 (netfxsp.050727-3000)
    程式碼基底: file:///C:/WINNT/assembly/GAC_MSIL/System.Runtime.Remoting/2.0.0.0__b77a5c561934e089/System.Runtime.Remoting.dll
----------------------------------------
System.Windows.Forms.resources
    組件版本: 2.0.0.0
    Win32 版本: 2.0.50727.1433 (REDBITS.050727-1400)
    程式碼基底: file:///C:/WINNT/assembly/GAC_MSIL/System.Windows.Forms.resources/2.0.0.0_zh-CHT_b77a5c561934e089/System.Windows.Forms.resources.dll
----------------------------------------
mscorlib.resources
    組件版本: 2.0.0.0
    Win32 版本: 2.0.50727.3634 (GDR.050727-3600)
    程式碼基底: file:///C:/WINNT/Microsoft.NET/Framework/v2.0.50727/mscorlib.dll
----------------------------------------

************** JIT 偵錯 **************
若要啟用 Just-In-Time (JIT) 偵錯功能,則必須在
此應用程式或電腦的 .config 檔案中,設定
system.windows.forms 區段內的 jitDebugging 值。
且該應用程式也必須在啟用偵錯的狀態下進行
編譯。

例如:

<configuration>
    <system.windows.forms jitDebugging="true" />
</configuration>

當 JIT 偵錯功能啟用後,會將所有未處理的例外
狀況傳送給電腦上已註冊的 JIT 偵錯工具進行處
理,而不是使用這個對話方塊來處理。

2012年11月9日 星期五

[學習] If Else 判斷式 細節注意~

AndAlso運算子


問題(Problem):
從資料庫撈資料時~
若某資料型態為日期(or 其它特殊型態)時~
用 Foor-loop or while-loop 取得資料列(並顯示在畫面上)~
用以下的 If判斷式 會出錯~

答案(Answer):
因為 If 判斷式~ 在判斷時會同時判斷 i是否符合條件 以及 arr(i + 1)是否符合條件~
故在此判斷式~ 便會出錯~
從字串 "XXXX" 至型別 'Date' 的轉換是無效的。

For i As Integer = 1 To 10
     If i = 3 And CDate(arr(i + 1)).ToShortDateString = "1900/1/1" Then
          C.Text = "尚無資料"
     End If
Next

需更改為
當判斷 i不符合時~ 就不會再判斷 arr(i + 1) 是否符合~
(1)
For i As Integer = 1 To 10
     If i = 3 Then
          If CDate(arr(i + 1)).ToShortDateString = "1900/1/1" Then
               C.Text = "尚無資料"
          End If
     End If
Next

或者
當更改判斷式 If AndAlso 判i不符合~ 就不會再判斷 arr(i + 1) 是否符合~
(2)

For i As Integer = 1 To 10

     If i = 3 And CDate(arr(i + 1)).ToShortDateString = "1900/1/1" Then
          C.Text = "尚無資料"
     End If

Next


或者
在判斷式之前 必須判斷 arr(i+1) 是否為日期型態
(3)
For i As Integer = 1 To 10

If IsDate(arr(i + 1)) = True Then
     '是日期型態
     If i = 3 And CDate(arr(i + 1)).ToShortDateString = "1900/1/1" Then
          C.Text = "尚無資料"
     End If
Else
     '不是日期型態
End If
Next


參考:

運算子 AndAlso 和 OrElse
VB.NET's Logical Operators AndAlso and OrElse









2012年11月8日 星期四

[除錯] DataGridView1.CurrentRow with EVENT DataGridView1_SelectionChanged

問題(problem):
點選 DataGridView 的表頭(Header)會錯誤 

錯誤訊息(Error Msg):
並未將物件參考設定為物件的執行個體

Private Sub DataGridView1_SelectionChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles DataGridView1.SelectionChanged
   
     '出錯的Code
     If DataGridView1.CurrentRow.Index <> -1 Then
           'do something
     End If
     
     '改成物件是否 Nothing
      If DataGridView1.CurrentRow IsNot Nothing Then
           'do something
      End If
End Sub

或改成


'確定是否點選到DataGridView的某行資料列 [C#]
if (this.DataGridView.SelectedRows.Count != 0) {}

DataGridView - EditOnEnter
DataGridView 控制項 (Windows Form)

[學習] MdiParent.FindForm().MdiChildren

問題(Problem):
非MDI的表單(Search_Personal)
1.要呼叫MDI的子表單(MGMT_Personal)的副程式
.DisplayDataRow(staffarr, DirectCast(f, MGMT_Personal).FetchDataRow(staffarr))
.SetBindingControlStatus()

並且經由非MDI的表單(Search_Personal)的事件DGV1_SelectionChanged
即時更改MDI的子表單(MGMT_Personl)的DataGridView1內容!!

2.非MDI的表單(Search_Personal)MDI的子表單(MGMT_Personal)的值也可以

關係(Relationship):
父表單(MdiParent)MAIN_ligoHRsys下的子表單(MdiChidren)MGMT_Personal
Search_Personal (Not MDI)不屬於MDI...

流程(Step):
MGMT_Personal 開啟 Search_Personal
Search_Personal 呼叫 MGMT_Personal 的副程式


Public Class MGMT_Personal
    Dim frm As Search_Personal
    Private Sub ToolStripButton9_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ToolStripButton9.Click
        '未產生frm物件 才可New Search_Personal 否則會N個 New Search_Personal
        If frm Is Nothing OrElse frm.IsDisposed Then frm = New Search_Personal
        frm.Show()
        frm.Focus()
     End Sub

End Class



Public Class Search_Personal
    Private Sub DataGridView1_SelectionChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles DataGridView1.SelectionChanged

        If DataGridView1.CurrentRow IsNot Nothing Then
            Dim paraName(0) As String
            Dim paraValue(0) As String
            paraName(0) = "staff_sn"
            paraValue(0) = Trim(DataGridView1.CurrentRow.Cells(6).Value.ToString)

            Dim staffDB As New Class_db
            Dim staffarr(14) As String

            staffarr = staffDB.reReader("select * from [employee] where staff_sn = @staff_sn", paraName, paraValue)
            If staffarr(0) Is Nothing Then
                Exit Sub
            End If

            staffDB.Dispose()

            '找出父表單MAIN_ligoHRsys下的子表單MGMT_Personal
            Dim aryf As Form() = MAIN_ligoHRsys.FindForm().MdiChildren
            For Each f As Form In aryf
                If f.Name = "MGMT_Personal" Then
                    '呼叫父表單MAIN_ligoHRsys下的子表單MGMT_Personal的副程式並傳入參數
                    DirectCast(f, MGMT_Personal).DisplayDataRow(staffarr, DirectCast(f, MGMT_Personal).FetchDataRow(staffarr))
                    DirectCast(f, MGMT_Personal).SetBindingControlStatus()
                    Exit For
                End If
            Next
        End If
    End Sub
End Class

[學習] Controls.Find with Option Strict On


DirectCast


原始為---
Option Strict Off
            For i As Integer = 1 To 10
                Dim C As TextBox = Me.Controls.Find("TextBox" & i, True)(0)
                If i = 10 Then
                    C.Text = arr(i + 4).ToString
                Else
                    C.Text = arr(i + 1).ToString
                End If
            Next
        End If

更改為---

Option Strict On

會發生 Error 隱含轉換
錯誤1 Option Strict On 不允許從 'System.Windows.Forms.Control' 到 'System.Windows.Forms.TextBox' 的隱含轉換。
錯誤2 Option Strict On 不允許從 'System.Windows.Forms.Control' 到 'System.Windows.Forms.ComboBox' 的隱含轉換。
錯誤3 Option Strict On 不允許從 'System.Windows.Forms.Control' 到 'System.Windows.Forms.DataGridView' 的隱含轉換。

故改為---

For i As Integer = 1 To 10
      Dim C As TextBox = DirectCast(Me.Controls.Find("TextBox" & i, True)(0), TextBox)                     
           If i = 10 Then
               C.Text = arr(i + 4).ToString
           Else
               C.Text = arr(i + 1).ToString
           End If
Next

錯誤4 Option Strict On 不允許從 'Object' 到 'String' 的隱含轉換

DataGridView1.Rows(i).Cells(2).Value = _
Trim(DataGridView1.Rows(i).Cells(2).Value) + Trim(DataGridView1.Rows(i).Cells(3).Value)

故改為---

DataGridView1.Rows(i).Cells(2).Value = _
Trim(DataGridView1.Rows(i).Cells(2).Value.ToString) + Trim(DataGridView1.Rows(i).Cells(3).Value.ToString)

[學習] Create Dynamic Form with Option Strict On


Option Strict 陳述式

Option Strict On 不允許晚期繫結


原始為---

Option Strict Off

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

        Dim frmEdit As Object = Nothing
        Select Case TabControl1.SelectedIndex
            Case 0
                frmEdit = New Edit_education
                DirectCast(frmEdit, Form).StartPosition = FormStartPosition.CenterParent
            Case 1
                frmEdit = New Edit_family
                DirectCast(frmEdit, Form).StartPosition = FormStartPosition.CenterParent
            Case 2
                frmEdit  = New Edit_credential
                DirectCast(frmEdit, Form).StartPosition = FormStartPosition.CenterParent
        End Select
        frmEdit.ShowDialog
        If frmEdit.DialogResult = Windows.Forms.DialogResult.OK Then
                'do something
        End If
End Sub


更改為---

Option Strict On

會發生 Error 隱含轉換
錯誤1     Object 不允許 frmEdit.ShowDialog 晚期繫結
錯誤2     Object 不允許 frmEdit.DialogResult 晚期繫結

因此改為---

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


        Dim dlgResult As DialogResult
        Select Case TabControl1.SelectedIndex
            Case 0
                Dim frmEdit As Edit_education = New Edit_education
                DirectCast(frmEdit, Form).StartPosition = FormStartPosition.CenterParent
                dlgResult = frmEdit.ShowDialog 'Option Strict On 不允許晚期繫結 因為宣告為Object
            Case 1
                Dim frmEdit As Edit_family = New Edit_family
                DirectCast(frmEdit, Form).StartPosition = FormStartPosition.CenterParent
                dlgResult = frmEdit.ShowDialog 'Option Strict On 不允許晚期繫結 因為宣告為Object
            Case 2
                Dim frmEdit As Edit_credential = New Edit_credential
                DirectCast(frmEdit, Form).StartPosition = FormStartPosition.CenterParent
                dlgResult = frmEdit.ShowDialog 'Option Strict On 不允許晚期繫結 因為宣告為Object
        End Select

        If dlgResult = Windows.Forms.DialogResult.OK Then
                'do something
        End If
End Sub

或者改為---

        Dim frmEditN As Form = Nothing
        Select Case TabControl1.SelectedIndex
            Case 0
                Dim frmEdit As Edit_education = New Edit_education
                DirectCast(frmEdit, Form).StartPosition = FormStartPosition.CenterParent
                frmEditN = frmEdit
            Case 1
                Dim frmEdit As Edit_family = New Edit_family
                DirectCast(frmEdit, Form).StartPosition = FormStartPosition.CenterParent
                frmEditN = frmEdit
        End Select

        frmEditN.ShowDialog()
        If frmEditN.DialogResult = Windows.Forms.DialogResult.OK Then
                'do something
        End If