Solved

Problems with DEVMODE

Posted on 2002-06-05
6
1,442 Views
Last Modified: 2012-08-14
Hello Experts !

I have to realize a printer setup dialog (PrintDlg) and have to save the printers properties to registry without changing the properties of any printer and reverse.

The reason is that i have to print with following Crystal Report function:

Declare Function PESelectPrinter Lib "crpe32.dll" (ByVal printJob%, ByVal PrinterDriver$, ByVal PrinterName$, ByVal PortName$, DevMode As Any) As Integer

This function needs a DEVMODE which i have to Store to store printer setting.

After hard research i found a solution to read and write the DEVMODE, but it seems not to be bulletproof. Can anybody say me where the bug could be ?

Further (this is my main question)i get constantly the same values for dmPaperLength and dmPaperWidth although i choosed an other paper format than A4 (german paper format) in the print dialog.

My next approach was to read the dmPaperSize to retrieve the paper format indirectly by using a self generated lookup-table. The problem here is, that i get numbers for the dmPaperSize which aren't in my table.

So i can't realize true preview of the paper and it's margins.

Here is the interesting part of the Code:

Public Type PRINTDLG_TYPE
   lStructSize As Long
   hwndOwner As Long
   hDevMode As Long
   hDevNames As Long
   hDC As Long
   flags As Long
   nFromPage As Integer
   nToPage As Integer
   nMinPage As Integer
   nMaxPage As Integer
   nCopies As Integer
   hInstance As Long
   lCustData As Long
   lpfnPrintHook As Long
   lpfnSetupHook As Long
   lpPrintTemplateName As String
   lpSetupTemplateName As String
   hPrintTemplate As Long
   hSetupTemplate As Long
End Type

Public Function SelectPrinter(iPrintJob As Integer) As Boolean
    Dim sMsg As String

    Select Case True
        Case iPrintJob = 0
            sMsg = "Ungültige Druckauftrags-Nr. !"
        Case Len(Trim(DriverName)) = 0
            sMsg = "Name des Druckertreibers fehlt!"
        Case Len(Trim(DeviceName)) = 0
            sMsg = "Drucker-Name fehlt!"
        Case Len(Trim(Port)) = 0
            sMsg = "Drucker-Port fehlt!"
        Case GetArrayDimensions(bufDevMode) = 0
            sMsg = "Druckereinstellungen fehlen!"
        Case UBound(bufDevMode) <= Len(crDevMode)
            sMsg = "Die Druckereinstellungen sind ungültig !"
        Case PESelectPrinter(iPrintJob, DriverName, DeviceName, Port, bufDevMode(1)) = 0
            sMsg = "Die Druckerauswahl ist fehlgeschlagen !"
        Case Else
            SelectPrinter = True
            Exit Function
    End Select
    Call Err.Raise(iPrintJob, "crpe32.dll", sMsg)

End Function

Public Sub GetPrinterSettings(AppName As String, Section As String)
    DriverName = GetSetting(AppName, Section, "DriverName", "")
    DeviceName = GetSetting(AppName, Section, "DeviceName", "")
    Port = GetSetting(AppName, Section, "Port", "")
    Call HexStr2ByteArray(bufDevMode, GetSetting(AppName, Section, "DEVMODE", ""))
    Call HexStr2ByteArray(bufDevName, GetSetting(AppName, Section, "DEVNAME", ""))
    ' CSErrorHandler begin - please do not modify or remove this line
End Sub

Public Sub SavePrinterSettings(AppName As String, Section As String)
    If Me.initialized And Len(Section) > 0 Then
        Call SaveSetting(AppName, Section, "DriverName", DriverName)
        Call SaveSetting(AppName, Section, "DeviceName", DeviceName)
        Call SaveSetting(AppName, Section, "Port", Port)
        Call SaveSetting(AppName, Section, "DEVMODE", ByteArray2HexStr(bufDevMode))
        Call SaveSetting(AppName, Section, "DEVNAME", ByteArray2HexStr(bufDevName))
    End If
End Sub

Private Function ByteArray2HexStr(ByteArray() As Byte) As String
    Dim i As Long
    Dim TMP As String

    For i = LBound(ByteArray) To UBound(ByteArray)
        TMP = TMP & Right("0" & Hex(ByteArray(i)), 2)
    Next
    ByteArray2HexStr = TMP
End Function

Private Sub HexStr2ByteArray(ByteArray() As Byte, Text As String)
    Dim i As Long

    If Len(Text) > 0 Then
        ReDim ByteArray(1 To Len(Text) \ 2)
        For i = LBound(ByteArray) To UBound(ByteArray)
            ByteArray(i) = "&H" & Mid(Text, (2 * i) - 1, 2)
        Next
    End If
End Sub

Private Sub GetPaperDescription(NamePaperSize As String, tmpPaperWidth As Long, tmpPaperHeight As Long)
    Select Case bufDevMode(47) + 256 * bufDevMode(48)
        Case DMPAPER_LETTER
            NamePaperSize = "Blatt 8,5 x 11 Inch"
            tmpPaperWidth = 2159
            tmpPaperHeight = 2794
        Case DMPAPER_LEGAL
            NamePaperSize = "Blatt 8,5 x 14 Inch"
            tmpPaperWidth = 2159
            tmpPaperHeight = 3556
        Case DMPAPER_10X11
            NamePaperSize = "10 x 11 Inch"
            tmpPaperWidth = 2540
            tmpPaperHeight = 2794
        Case DMPAPER_10X14
            NamePaperSize = "10 x 14 Inch"
            tmpPaperWidth = 2540
            tmpPaperHeight = 3556
        Case DMPAPER_11X17
            NamePaperSize = "11 x 17 Inch"
            tmpPaperWidth = 2794
            tmpPaperHeight = 4318
        Case DMPAPER_15X11
            NamePaperSize = "15 x 11 Inch"
            tmpPaperWidth = 3810
            tmpPaperHeight = 2794
        Case DMPAPER_9X11
            NamePaperSize = "9 x 11 Inch"
            tmpPaperWidth = 2286
            tmpPaperHeight = 2794
           
        Case DMPAPER_A_PLUS
            NamePaperSize = "A Plus Blatt"
        Case DMPAPER_A2
            NamePaperSize = "DIN A2 Blatt"
        Case DMPAPER_A3
            NamePaperSize = "DIN A3 Blatt"
        Case DMPAPER_A3_EXTRA
            NamePaperSize = "DIN A3 Extra Blatt"
        Case DMPAPER_A3_EXTRA_TRANSVERSE
            NamePaperSize = "DIN A3 Extra Blatt querlaufend"
        Case DMPAPER_A3_TRANSVERSE
            NamePaperSize = "DIN A3 Blatt querlaufend"
           
        Case DMPAPER_A4
            NamePaperSize = "DIN A4 Blatt"
            tmpPaperWidth = 2100
            tmpPaperHeight = 2970
           
        Case DMPAPER_A4_EXTRA
            NamePaperSize = "DIN A4 Extra Blatt"
        Case DMPAPER_A4_PLUS
            NamePaperSize = "DIN A4 Plus Blatt"
        Case DMPAPER_A4_TRANSVERSE
            NamePaperSize = "DIN A4 querlaufend"
           
        Case DMPAPER_A4SMALL
            NamePaperSize = "DIN A4 klein (210 x 297 Millimeter) Blatt"
            tmpPaperWidth = 2100
            tmpPaperHeight = 2970
        Case DMPAPER_A5
            NamePaperSize = "DIN A5 Blatt"
            tmpPaperWidth = 1485
            tmpPaperHeight = 2100
           
        Case DMPAPER_A5_EXTRA
            NamePaperSize = "DIN A5 Extra Blatt"
        Case DMPAPER_A5_TRANSVERSE
            NamePaperSize = "DIN A5 querlaufend"
        Case DMPAPER_B_PLUS
            NamePaperSize = "B Plus Blatt"
        Case DMPAPER_B4
            NamePaperSize = "B4 Blatt"
        Case DMPAPER_B5
            NamePaperSize = "B5 Blatt"
        Case DMPAPER_B5_EXTRA
            NamePaperSize = "B5 Extra Blatt"
        Case DMPAPER_B5_TRANSVERSE
            NamePaperSize = "B5 Blatt querlaufend"
           
        Case DMPAPER_CSHEET
            NamePaperSize = "C Blatt (17 x 22 Inch)"
            tmpPaperWidth = 4318
            tmpPaperHeight = 5588
        Case DMPAPER_DSHEET
            NamePaperSize = "D Blatt (22x34 Inch)"
            tmpPaperWidth = 5588
            tmpPaperHeight = 8636
        Case DMPAPER_ENV_10
            NamePaperSize = "Briefumschlag 10 (4,125 x 9,5 Inch)"
            tmpPaperWidth = 1048
            tmpPaperHeight = 2413
        Case DMPAPER_ENV_11
            NamePaperSize = "Briefumschlag 11 (4,5 x 10,375 Inch)"
            tmpPaperWidth = 1143
            tmpPaperHeight = 2635
        Case DMPAPER_ENV_12
            NamePaperSize = "Briefumschlag 12 (4,75 x 11 Inch)"
            tmpPaperWidth = 1207
            tmpPaperHeight = 2794
        Case DMPAPER_ENV_14
            NamePaperSize = "Briefumschlag 14 (5 x 11,5 Inch)"
            tmpPaperWidth = 1270
            tmpPaperHeight = 2921
        Case DMPAPER_ENV_9
            NamePaperSize = "Briefumschlag 9 (3,875 x 8,875 Inch)"
            tmpPaperWidth = 984
            tmpPaperHeight = 2254
        Case DMPAPER_ENV_B4
            NamePaperSize = "Briefumschlag B4 (250 x 353 Millimeter)"
            tmpPaperWidth = 2500
            tmpPaperHeight = 3530
        Case DMPAPER_ENV_B5
            NamePaperSize = "Briefumschlag B5 (176 x 250 Millimeter)"
            tmpPaperWidth = 1760
            tmpPaperHeight = 2500
        Case DMPAPER_ENV_B6
            NamePaperSize = "Briefumschlag B6 (176 x 125 Millimeter)"
            tmpPaperWidth = 1760
            tmpPaperHeight = 1250
        Case DMPAPER_ENV_C3
            NamePaperSize = "Briefumschlag C3 (324 x 458 Millimeter)"
            tmpPaperWidth = 3240
            tmpPaperHeight = 4580
        Case DMPAPER_ENV_C4
            NamePaperSize = "Briefumschlag C4 (229 x 324 Millimeter)"
            tmpPaperWidth = 2290
            tmpPaperHeight = 3240
        Case DMPAPER_ENV_C5
            NamePaperSize = "Briefumschlag C5 (162 x 229 Millimeter)"
            tmpPaperWidth = 1620
            tmpPaperHeight = 2290
        Case DMPAPER_ENV_C6
            NamePaperSize = "Briefumschlag C6 (114 x 162 Millimeter)"
            tmpPaperWidth = 1140
            tmpPaperHeight = 1620
        Case DMPAPER_ENV_C65
            NamePaperSize = "Briefumschlag 10 (4,125 x 9,5 Inch)"
            tmpPaperWidth = 1048
            tmpPaperHeight = 2413
        Case DMPAPER_ENV_DL
            NamePaperSize = "Briefumschlag 10 (4,125 x 9,5 Inch)"
            tmpPaperWidth = 1048
            tmpPaperHeight = 2413
           
        Case DMPAPER_ENV_INVITE
            NamePaperSize = "Einladungs Briefumschlag"
           
        Case DMPAPER_ENV_ITALY
            NamePaperSize = "Italienischer Briefumschlag (110 x 230 Millimeter)"
            tmpPaperWidth = 1110
            tmpPaperHeight = 2300
        Case DMPAPER_ENV_MONARCH
            NamePaperSize = "Monarchischer Briefumschlag (3,875 x 7,5 ' Inch)"
            tmpPaperWidth = 984
            tmpPaperHeight = 1905
        Case DMPAPER_ENV_PERSONAL
            NamePaperSize = "Persönlicher Briefumschlag (3,625 x 6,5 ' Inch)"
            tmpPaperWidth = 921
            tmpPaperHeight = 1651
        Case DMPAPER_ESHEET
            NamePaperSize = "E Blatt (34 x 44 Inch)"
            tmpPaperWidth = 8636
            tmpPaperHeight = 11176
        Case DMPAPER_EXECUTIVE
            NamePaperSize = "Executive Blatt (7.25 x 10,5 Inch)"
            tmpPaperWidth = 1842
            tmpPaperHeight = 2667
        Case DMPAPER_FANFOLD_LGL_GERMAN
            NamePaperSize = "Deutscher Rechtlicher Fanfold (8,5 x 13 Inch)"
            tmpPaperWidth = 2159
            tmpPaperHeight = 3302
        Case DMPAPER_FANFOLD_STD_GERMAN
            NamePaperSize = "Deutscher Standard Fanfold (8,5 x 12  Inch)"
            tmpPaperWidth = 2159
            tmpPaperHeight = 3048
        Case DMPAPER_FANFOLD_US
            NamePaperSize = "US Standard Fanfold (14,875 + 11 Inch)"
            tmpPaperWidth = 3778
            tmpPaperHeight = 2794
        Case DMPAPER_FIRST
            NamePaperSize = "Blatt 8,5 x 11 Inch"
            tmpPaperWidth = 2159
            tmpPaperHeight = 2794
        Case DMPAPER_FOLIO
            NamePaperSize = "Folin 8,5 + 13 Inch"
            tmpPaperWidth = 2159
            tmpPaperHeight = 3302
           
        Case DMPAPER_ISO_B4
            NamePaperSize = "ISO B4 Blatt"
        Case DMPAPER_JAPANESE_POSTCARD
            NamePaperSize = "Japanische Postkarte"
           
        Case DMPAPER_LAST
            NamePaperSize = "Deutscher Rechtlicher Fanfold (8,5 x 13 Inch)"
            tmpPaperWidth = 2159
            tmpPaperHeight = 3302
        Case DMPAPER_LEDGER
            NamePaperSize = "Ledger (17x11 Inch)"
            tmpPaperWidth = 4318
            tmpPaperHeight = 2794
       
        Case DMPAPER_LEGAL_EXTRA
            NamePaperSize = "Rechtlich Extra"
        Case DMPAPER_LETTER_EXTRA
            NamePaperSize = "Blatt Extra"
        Case DMPAPER_LETTER_EXTRA_TRANSVERSE
            NamePaperSize = "Blatt Extra querlaufend"
        Case DMPAPER_LETTER_PLUS
            NamePaperSize = "Blatt Plus"
        Case DMPAPER_LETTER_TRANSVERSE
            NamePaperSize = "Blatt querlaufend"
       
        Case DMPAPER_LETTERSMALL
            NamePaperSize = "Blatt klein (8,5 x 11 Inch)"
            tmpPaperWidth = 2159
            tmpPaperHeight = 2794
        Case DMPAPER_NOTE
            NamePaperSize = "Note Blatt (8,5 x 11 Inch)"
            tmpPaperWidth = 2159
            tmpPaperHeight = 2794
        Case DMPAPER_QUARTO
            NamePaperSize = "Quarto Blatt (215 x 275 Millimeter)"
            tmpPaperWidth = 2150
            tmpPaperHeight = 2750
        Case DMPAPER_STATEMENT
            NamePaperSize = "Statement Blatt (5,5 x 8,5 Inch)"
            tmpPaperWidth = 1397
            tmpPaperHeight = 2159
        Case DMPAPER_TABLOID
            NamePaperSize = "Tabloid Blatt (11 x 17 Inch)"
            tmpPaperWidth = 2794
            tmpPaperHeight = 4318
       
        Case DMPAPER_TABLOID_EXTRA
            NamePaperSize = "Tabloid Extra Blatt"
        Case DMPAPER_USER
            NamePaperSize = "Benutzerdefinierte Größe"
       
        Case Else
            NamePaperSize = "Papierformat " & bufDevMode(47) + 256 * (bufDevMode(48) And &H7F) & " nicht gefunden !"
            tmpPaperWidth = 2100
            tmpPaperHeight = 2970
    End Select
End Sub

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

HOPE ANYBODY CAN HELP ! I FOUND NOTHING BETTER THAN THAT IN THE WEB.

REGARDS

V.K.
Public Const CCHDEVICENAME = 32
Public Const CCHFORMNAME = 32

Public Type DEVNAMES
        wDriverOffset As Integer
        wDeviceOffset As Integer
        wOutputOffset As Integer
        wDefault As Integer
End Type

Public Type DEVMODE
    dmDeviceName(CCHDEVICENAME) As Byte 'bufDevMode(1)
    dmSpecVersion As Integer 'bufDevMode(33)
    dmDriverVersion As Integer 'bufDevMode(35)
    dmSize As Integer  'bufDevMode(37)
    dmDriverExtra As Integer  'bufDevMode(39)
    dmFields As Long 'bufDevMode(41)
    dmOrientation As Integer 'bufDevMode(45)
    dmPaperSize As Integer 'bufDevMode(47)
    dmPaperLength As Integer 'bufDevMode(49)
    dmPaperWidth As Integer 'bufDevMode(51)
    dmScale As Integer
    dmCopies As Integer
    dmDefaultSource As Integer
    dmPrintQuality As Integer
    dmColor As Integer
    dmDuplex As Integer
    dmYResolution As Integer
    dmTTOption As Integer
    dmCollate As Integer
    dmFormName(CCHFORMNAME) As Byte
    dmUnusedPadding As Integer
    dmBitsPerPel As Long
    dmPelsWidth As Long
    dmPelsHeight As Long
    dmDisplayFlags As Long
    dmDisplayFrequency As Long
End Type


Public Sub SetupPrinter(ApphInstance As Long, frmHWnd As Long)
    Dim hMemMode As Long
    Dim pMemMode As Long
    Dim hMemName As Long
    Dim pMemName As Long
    Dim PrintDialog As PRINTDLG_TYPE
    Dim pPrt As Printer
    Dim sMsg As String
    Dim phPrinter As Long

    Select Case True
        Case GetArrayDimensions(bufDevMode) = 0
        Case UBound(bufDevMode) <= Len(crDevMode)
        Case Else 'Falls Druckereinstellungen in der Registry hinterlegt
            hMemMode = GlobalAlloc(GMEM_MOVEABLE Or GMEM_ZEROINIT, UBound(bufDevMode))  'Speicherblock erstellen
            hMemName = GlobalAlloc(GMEM_MOVEABLE Or GMEM_ZEROINIT, UBound(bufDevName))  'Speicherblock erstellen
            pMemMode = GlobalLock(hMemMode) 'Speicherblock Locken und Pointer ermitteln
            pMemName = GlobalLock(hMemName) 'Speicherblock Locken und Pointer ermitteln
            CopyMemory ByVal pMemMode, bufDevMode(1), UBound(bufDevMode) 'Struktur in den Speicherblock Kopieren
            CopyMemory ByVal pMemName, bufDevName(1), UBound(bufDevName) 'Struktur in den Speicherblock Kopieren
            GlobalUnlock hMemMode 'Speicherblock Unlocken
            GlobalUnlock hMemName 'Speicherblock Unlocken
    End Select

    With PrintDialog
        .hInstance = ApphInstance
        .hwndOwner = frmHWnd
        .lStructSize = Len(PrintDialog)
        .hDevMode = hMemMode
        .hDevNames = hMemName
        .flags = PD_PRINTSETUP
        .nFromPage = 1
        .nToPage = 15
        .nMinPage = 1
        .nMaxPage = 15
    End With

    If PrintDlg(PrintDialog) = 0 Then
        sMsg = GetCommDlgErr
        If Len(sMsg) > 0 Then Call Err.Raise(0, "comdlg32.dll", sMsg)
    Else
        ReDim bufDevMode(1 To GlobalSize(PrintDialog.hDevMode))
        ReDim bufDevName(1 To GlobalSize(PrintDialog.hDevNames))

        Call Text2ByteArray(bufDevMode, String(UBound(bufDevMode), Chr(FillByte)), FillByte)
        Call Text2ByteArray(bufDevName, String(UBound(bufDevName), Chr(FillByte)), FillByte)

        pMemMode = GlobalLock(PrintDialog.hDevMode)
        pMemName = GlobalLock(PrintDialog.hDevNames)
       
        Call CopyMemory(crDevMode, ByVal pMemMode, Len(crDevMode))
        Call CopyMemory(crDevName, ByVal pMemName, Len(crDevName))

        Call CopyMemory(bufDevMode(1), ByVal pMemMode, UBound(bufDevMode))
        Call CopyMemory(bufDevName(1), ByVal pMemName, UBound(bufDevName))

        Call GlobalUnlock(PrintDialog.hDevMode)
        Call GlobalUnlock(PrintDialog.hDevNames)


        'Printers Collection durchlaufen, um die Treibernamen und Ports für den Druckernamen aus DevMode-Struktur,
        'die vom Standarddialog zurückgegeben wurde, zu erhalten.
        DeviceName = Trim(ByteArray2Str(crDevMode.dmDeviceName))
        If InStr(1, DeviceName, Chr(0)) > 0 Then DeviceName = Mid(DeviceName, 1, InStr(1, DeviceName, Chr(0)) - 1)
               
        Dim i As Long
        i = Len(DeviceName)
               
        For Each pPrt In Printers
            If DeviceName = Left(pPrt.DeviceName, i) Then
                DriverName = pPrt.DriverName
                Port = pPrt.Port
                Exit For
            End If
        Next

    End If

    m_Orientation = bufDevMode(45) 'this works
    Debug.Print bufDevMode(49) + 256 * (bufDevMode(50) And &H7F) 'this doesn't work
    Debug.Print bufDevMode(51) + 256 * (bufDevMode(52) And &H7F) 'this doesn't work

    Call GlobalFree(PrintDialog.hDevMode)
    Call GlobalFree(PrintDialog.hDevNames)
    Call UserControl_Paint
End Sub



0
Comment
Question by:VK
6 Comments
 
LVL 2

Expert Comment

by:corvanderlinden
Comment Utility
see :http://www.mvps.org/vb/
and search there for PrnInfo.zip
0
 
LVL 2

Expert Comment

by:corvanderlinden
Comment Utility
see
http://www.mvps.org/vb/
and search there for PrnInfo.zip
0
 
LVL 6

Author Comment

by:VK
Comment Utility
Hello corvanderlinden !

I have already downloaded the zip file and tested the project.

Unfortunely there is no code for getting DEVMODE properties from a printer-setup dialog.

You can get the DEVMODE properties of an installed printer, but this i not what i need.

As said before:

I have to call

Declare Function PESelectPrinter Lib "crpe32.dll" (ByVal printJob%, ByVal PrinterDriver$, ByVal PrinterName$,
ByVal PortName$, DevMode As Any) As Integer

with a devmode generated on the fly.

I should get the DEVMODE for a possible configuration without changing any printers settings.

regards

V.K.
0
Why You Should Analyze Threat Actor TTPs

After years of analyzing threat actor behavior, it’s become clear that at any given time there are specific tactics, techniques, and procedures (TTPs) that are particularly prevalent. By analyzing and understanding these TTPs, you can dramatically enhance your security program.

 
LVL 6

Author Comment

by:VK
Comment Utility
P.S.

When i call SetupPrinter a second time and confirm the dialog with OK (without changing any properties) i get the correct PaperLength and PaperWidth.

So the problem is solveable when i can suppress the showing of the dialog if calling the dialog is necessary.

V.K.

0
 
LVL 49

Expert Comment

by:DanRollins
Comment Utility
Hi VK,
It appears that you have forgotten this question. I will ask Community Support to close it unless you finalize it within 7 days. I will ask a Community Support Moderator to:

    Refund points and save as a 0-pt PAQ.

VK, Please DO NOT accept this comment as an answer.
EXPERTS: Post a comment if you are certain that an expert deserves credit.  Explain why.
==========
DanRollins -- EE database cleanup volunteer
0
 
LVL 1

Accepted Solution

by:
Computer101 earned 0 total points
Comment Utility
Question placed in PAQ

Computer101
E-E Admin
0

Featured Post

Better Security Awareness With Threat Intelligence

See how one of the leading financial services organizations uses Recorded Future as part of a holistic threat intelligence program to promote security awareness and proactively and efficiently identify threats.

Join & Write a Comment

When designing a form there are several BorderStyles to choose from, all of which can be classified as either 'Fixed' or 'Sizable' and I'd guess that 'Fixed Single' or one of the other fixed types is the most popular choice. I assume it's the most p…
If you need to start windows update installation remotely or as a scheduled task you will find this very helpful.
As developers, we are not limited to the functions provided by the VBA language. In addition, we can call the functions that are part of the Windows operating system. These functions are part of the Windows API (Application Programming Interface). U…
Show developers how to use a criteria form to limit the data that appears on an Access report. It is a common requirement that users can specify the criteria for a report at runtime. The easiest way to accomplish this is using a criteria form that a…

771 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

10 Experts available now in Live!

Get 1:1 Help Now