PDA

View Full Version : مشکل در تبدیل تابع Api جهت استفاده در دات نت



niloufar
دوشنبه 30 مرداد 1385, 19:39 عصر
سلام
در زمان VB6 خدابیامرز برای اینکه بتونیم از روی یه پنجره خاص فرم را جابجا کنیم (برای اینکه TitleBar رو شبیه سازی کنیم) از کد زیر استفاده می کردیم:


Const HTCAPTION = 2
Const WM_NCLBUTTONDOWN = &HA1
Private Declare Function ReleaseCapture Lib "user32" () As Long
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Any) As Long

Private Sub Form1_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseDown
Call ReleaseCapture()
Call SendMessage(hwnd, WM_NCLBUTTONDOWN, HTCAPTION, 0&)
End Sub


حالا میخواستم بدونم چه جوری میشه این کد رو در دات نت هم استفاده کرد.

ممنون

ghafoori
دوشنبه 30 مرداد 1385, 21:00 عصر
در دات نت برای any هیچ نوع خاصی در نظر گرفته نشده و بستگی به اطلاعاتی که می خواهید به تابع بفرستید نوع ان تعیین می شود مثلا گر عدد می فرستید عدد بنویسید یا اگر رشته می فرستید نوع را رشته در نر بگیرید
من نمی دانم تابع SendMessage چکاری انجام میدهد ولی خود مایکروسافت تابعی برای این کار گذاشته این مطلب در msdn بود



SendMessage Sends the specified message to a window or windows. Any of the following:
System.Windows.Forms.Control.DefWndProc
System.Windows.Forms.Control.WndProc
System.Windows.Forms.Form.DefWndProc
System.Windows.Forms.Form.WndProc

مثال استفاده از یکی از این توابع



Imports System
Imports System.Drawing
Imports System.Windows.Forms

Namespace csTempWindowsApplication1

Public Class Form1
Inherits System.Windows.Forms.Form

' Constant value was found in the "windows.h" header file.
Private Const WM_ACTIVATEAPP As Integer = &H1C
Private appActive As Boolean = True

<STAThread()> _
Shared Sub Main()
Application.Run(New Form1())
End Sub 'Main

Public Sub New()
MyBase.New()

Me.Size = New System.Drawing.Size(300, 300)
Me.Text = "Form1"
Me.Font = New System.Drawing.Font("Microsoft Sans Serif", 18.0!, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, CType(0, Byte))
End Sub

Protected Overrides Sub OnPaint(ByVal e As PaintEventArgs)

' Paint a string in different styles depending on whether the
' application is active.
If (appActive) Then
e.Graphics.FillRectangle(SystemBrushes.ActiveCapti on, 20, 20, 260, 50)
e.Graphics.DrawString("Application is active", Me.Font, SystemBrushes.ActiveCaptionText, 20, 20)
Else
e.Graphics.FillRectangle(SystemBrushes.InactiveCap tion, 20, 20, 260, 50)
e.Graphics.DrawString("Application is Inactive", Me.Font, SystemBrushes.ActiveCaptionText, 20, 20)
End If
End Sub
<System.Security.Permissions.PermissionSetAttribute (System.Security.Permissions.SecurityAction.Demand , Name:="FullTrust")> _
Protected Overrides Sub WndProc(ByRef m As Message)
' Listen for operating system messages
Select Case (m.Msg)
' The WM_ACTIVATEAPP message occurs when the application
' becomes the active application or becomes inactive.
Case WM_ACTIVATEAPP

' The WParam value identifies what is occurring.
appActive = (m.WParam.ToInt32() <> 0)

' Invalidate to get new text painted.
Me.Invalidate()

End Select
MyBase.WndProc(m)
End Sub
End Class
End Namespace

niloufar
چهارشنبه 01 شهریور 1385, 16:08 عصر
سلام
آقای غفوری ممنون
اما من از اینا نفهمیدم چطور باید اون کدهای مربوط به شبیه سازی TaskBar رو دات نتی کنم.
ضمن اینکه الان این تابع SendMessage یه جای دیگه هم مورد استفاده پیدا کرده:
http://www.barnamenevis.org/forum/showthread.php?p=258559#post258559

ضمنا الان یه نگاهی هم به کلاسهای Windows.Forms.Control و Windows.Forms.Form که شما گفتید انداختم، هیچ کدوم توابع WndProc , DefWndProc رو که نوشته بودید نداشتند!!!

niloufar
یک شنبه 05 شهریور 1385, 18:27 عصر
دوباره سلام
من هنوز منتظر جواب هستم!!

ghafoori
یک شنبه 05 شهریور 1385, 22:47 عصر
در دات نت برای any هیچ نوع خاصی در نظر گرفته نشده و بستگی به اطلاعاتی که می خواهید به تابع بفرستید نوع ان تعیین می شود
این توضیحات خود msdnدرباره نوع any است


In Visual Basic 6.0, you could declare a reference to an external procedure with the Declare statement and specify As Any for the data type of an argument or return type. The As Any keyword disabled type checking and allowed any data type to be passed in or returned.

In Visual Basic 2005, the As Any keyword is no longer supported. To ensure type safety, you must specifically declare the data type of all arguments and return values.

For example, the following declaration accepted either a string or a long data type as the second argument:

Copy Code
' Visual Basic 6.0
Declare Function LoadCursor Lib "user32" Alias "LoadCursorA"(ByVal hInstance As Long, ByVal lpCursorName As Any) As Long

' After upgrade to Visual Basic 2005
' UPGRADE_ISSUE: Declaring a parameter 'As Any' is not supported.
Declare Function LoadCursor Lib "user32" Alias "LoadCursorA"(ByVal hInstance As Integer, ByVal lpCursorName As Any) As Integer


What to do next
Determine where the declared function is being used in your code and what data type is being passed. If all occurrences pass the same data type, change the declaration to include that data type instead of As Any:

Declare Function LoadCursor Lib "user32" Alias "LoadCursorA"(ByVal hInstance As Integer, ByVal lpCursorName As String) As Integer

If you need to support multiple data types, create an overloaded version of the declaration for each data type:

Declare Function LoadCursor Lib "user32" Alias "LoadCursorA"(ByVal hInstance As Integer, ByVal lpCursorName As String) As Integer
Declare Function LoadCursor Lib "user32" Alias "LoadCursorA"(ByVal hInstance As Integer, ByVal lpCursorName As Integer) As Long

پس نوع ان را باید نسبت به ان چیزی که به تابع می فرستید تعیین کنید


ضمنا الان یه نگاهی هم به کلاسهای Windows.Forms.Control و Windows.Forms.Form که شما گفتید انداختم، هیچ کدوم توابع WndProc , DefWndProc رو که نوشته بودید نداشتند!!!

این توابع MustOverride هستند و برای استفاده باید حتما override شوند تا کار کنند من که مثال را برای شما گذاشتم

rezaei manesh
چهارشنبه 08 شهریور 1385, 18:20 عصر
کد vb6 خدتون رو با دات نت باز کنید شاید خود دات نت پیشنهادی برای این کد ها داد

حامد مصافی
پنج شنبه 09 شهریور 1385, 15:01 عصر
سلام
نیلوفر خانم فقط کافیه تا به جای Any از Object استفاده کنید. مشکل حل میشه
تقریباً در 99 درصد مواقع میشه این کار رو انجام داد و به نتیجه رسید

روی فرم دو لیبل قرار بدین و کد زیر رو کپی کنید
من دو روش مختلف برای حرکت فرم پیاده نوشتم:

در مواقعی که ویندوز هنگام حرکت پنجره محتویاتشو نشون نده روش دوم (که روی لیبل دوم اعمال میشه) محتویات پنجره رو نشون میده


Public Class Form1

Private Declare Function ReleaseCapture Lib "user32" () As Integer
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Integer, ByVal wMsg As Integer, ByVal wParam As Integer, ByVal lParam As Object) As Integer
Const HTCAPTION As Short = 2
Const WM_NCLBUTTONDOWN As Short = &HA1S

Dim xx, yy As Integer

Private Sub Label1_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Label1.MouseDown
Call ReleaseCapture()
Call SendMessage(Handle, WM_NCLBUTTONDOWN, HTCAPTION, 0)
End Sub

Private Sub Label2_MouseDown(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Label2.MouseDown
If e.Button = Windows.Forms.MouseButtons.Left Then
xx = e.Location.X
yy = e.Location.Y
End If
End Sub

Private Sub Label2_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Label2.MouseMove
If e.Button = Windows.Forms.MouseButtons.Left Then
Me.Left += (e.Location.X - xx)
Me.Top += (e.Location.Y - yy)
End If
End Sub
End Class

niloufar
یک شنبه 12 شهریور 1385, 18:57 عصر
سلام
آقای مصافی
1- یادمه شما اون موقع ها تو تالار VB6 کلی API کار بودید، خوشحالم که بعد از مدت ها دوباره تو این تالار فعال شدید.
2- روش دوم شما (بدون استفاده از Api) قشنگ بود و ایده خوبی داشت. اما اصلا بحث اساسی من سر مشکل تبدیل توابع API جهت استفاده در دات نت است که یکیش هم تو همین تاپیک گفتم. من قبلا هم به جای Any حدس زدم و Object گذاشتم اما مثلا در همین کدی که شما برای لیبل اول نوشتید (و البته قبلا هم تست شده بود) وقتی ماوس Down میشود و سپس Move میشود، درست کار میکنه، اما به محض اینکه ماوس را رها میکنم، روی خط فرمان SendMessage متوقف میکنه و رنگ زمینه اونو سبز میکنه (یعنی Error نیست) و مینویسه:


pinvokestackimbalance was detected

و با یه سری توضیحات که یعنی سازگار نیستند. و البته وقتی بدون هیچ تغییری دوباره Runش میکنم (اجرای ادامه نه اجرای از ابتدا) باز به محیط اجرا بر میگرده!!!

یا مثلا در پست زیر هم یه Api هست که دوست داشتم تبدیلش کنم و هر چی سعی کردم نشد (اونم any داره) اگه میتونید یه نگاهم به اون بکنید:
http://barnamenevis.org/forum/showpost.php?p=258559&postcount=13

خلاصه ما که سر در نیاوردیم!!

حامد مصافی
یک شنبه 12 شهریور 1385, 21:57 عصر
سلام
... من قبلا هم به جای Any حدس زدم و Object گذاشتم اما مثلا در همین کدی که شما برای لیبل اول نوشتید (و البته قبلا هم تست شده بود) وقتی ماوس Down میشود و سپس Move میشود، درست کار میکنه، اما به محض اینکه ماوس را رها میکنم، روی خط فرمان SendMessage متوقف میکنه و رنگ زمینه اونو سبز میکنه (یعنی Error نیست) و مینویسه:


pinvokestackimbalance was detected
و با یه سری توضیحات که یعنی سازگار نیستند. و البته وقتی بدون هیچ تغییری دوباره Runش میکنم (اجرای ادامه نه اجرای از ابتدا) باز به محیط اجرا بر میگرده!!!



سلام
خب من به این خطا بر نخوردم ولی فکر کنم دلیلشو بدونم
من فردا جواب شما رو پست می کنم (هی دارم وعده فردا میدم)


در مورد مشکلی هم که تو لینک فرموده بودید .... انشاالله فردا !!!!!!!!!

حامد مصافی
دوشنبه 13 شهریور 1385, 09:07 صبح
سلام
حدس میزدم این مشکل مربوط به انتخاب نوع باشه
با استفاده از نوع Integer مشکل حل شد
این بار تست هم کردم!



Public Class Form1

Private Declare Function ReleaseCapture Lib "user32" () As Integer
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Integer, ByVal wMsg As Integer, ByVal wParam As Integer, ByVal lParam As Integer) As Integer
Const HTCAPTION As Short = 2
Const WM_NCLBUTTONDOWN As Short = &HA1S

Private Sub Form_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseDown
Call ReleaseCapture()
Call SendMessage(Handle, WM_NCLBUTTONDOWN, HTCAPTION, 0)
End Sub
End Class

niloufar
یک شنبه 19 شهریور 1385, 15:06 عصر
سلام
بازم ممنون
اون لینک چی شد. نگاش کردید؟