News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

Graphing?

Started by cman, December 17, 2005, 04:15:23 PM

Previous topic - Next topic

cman

Anyone seen a tutorial on using the Windows API to graph ordered pairs of data on an X , Y coordinant graph? Thanks...

Krozgen

Not a tutorial have I seen, per say, but... what exactly are you looking to do? If you know your screen dimensions (which can be done using an api call, of course... invoke GetSystemMetrics,SM_CXSCREEN and invoke GetSystemMetrics,SM_CYSCREEN)... then you should be able to do the math and plot the points. One cheap way I did it was to simulate a mouse click in mspaint, which I opened up behind it :-P (Don't use that method!!!)

Anyways, here's a stupid, and most likely inefficient (it was my first attempt at assembly) program. It uses polar coordinates, instead of cartesian, but it'll move the mouse in a circle or a spiral. Using the same principles, you could easily make the mouse do a sin or cos wave, for example, and once you've done that with the mouse, it's a simple matter of... instead of moving the mouse, just drawing a point or line in between.

Code is as follows, please don't critique it too much :-P

movemouse.asm

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

    .386                       ; create 32 bit code
    .model flat, stdcall       ; 32 bit memory model
    option casemap :none       ; case sensitive

    include \masm32\include\windows.inc
    include \masm32\include\masm32.inc
    include \masm32\include\user32.inc
    include \masm32\include\kernel32.inc

    includelib \masm32\lib\masm32.lib
    includelib \masm32\lib\user32.lib
    includelib \masm32\lib\kernel32.lib

    WndProc   PROTO :DWORD,:DWORD,:DWORD,:DWORD ; define procedure

    .data

    dlgname     db "mouseprog",0
    PiInOneCircle    DWORD  2   ;2
    ThetaInOneCircle DWORD  10  ;10
    maxx             DWORD  ?
    maxy             DWORD  ?
    r                DWORD  ?
    rmod             REAL10 40.0
    midx             DWORD  ?
    midy             DWORD  ?
    theta            DWORD  ?
    xpos             DWORD  ?
    ypos             DWORD  ?
    status           WORD   ?

    .data?

    hInstance   dd ?          ; instance for dialogbox
    ;username    db 10 dup(?) ; maximal 10 bytes
    ;validserial db 50 dup(?) ; maximal 50 bytes
   
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
   
    .code

start:

    invoke GetSystemMetrics,SM_CXSCREEN
    mov maxx, eax
    invoke GetSystemMetrics,SM_CYSCREEN
    mov maxy, eax

    invoke GetModuleHandle, NULL ; ask windows for an instance
    mov hInstance, eax ; move it to hInstance
    invoke DialogBoxParam, hInstance, ADDR dlgname, NULL, ADDR WndProc, NULL ; open the DialogBox
    invoke ExitProcess, eax ; exit process

; -------------------------------------------------------------------------

WndProc proc hWin   :DWORD,
             uMsg   :DWORD,
             wParam :DWORD,
             lParam :DWORD

    .if uMsg == WM_COMMAND ; a button has been pressed

        .if wParam == 100  ; mouse circle
            invoke GetDlgItemInt, hWin, 150, OFFSET r, 10
            mov r,eax
            call DrawCircle
        .elseif wParam == 101  ; mouse spiral
            invoke GetDlgItemInt, hWin, 150, OFFSET r, 10
            mov r,eax
            call DrawSpiral
        .elseif wParam == 200   ; exit button
            invoke EndDialog,hWin,NULL ; EndDialog and return to exitprocess API
        .endif

    .elseif uMsg == WM_CLOSE ; X button

        invoke EndDialog,hWin,NULL ; EndDialog and return to exitprocess API

    .endif

    xor eax,eax     ; THIS LINE IS KEY! Without it, no dialog "window" appears,
                    ; and the program goes into an infinite loop.
    ret             
   
WndProc endp

; -------------------------------------------------------------------------

DrawCircle proc near

    push ebx
    push edi

    ;mov r, 300
    mov theta, 0

    mov eax, maxx
    shr eax, 1
    mov midx, eax
   
    mov eax, maxy
    shr eax, 1
    mov midy, eax

    ; At this point, r = 300, theta = 0, midx = maxx/2, midy = maxy/2
    ; Now, we want to draw our circle via the loop "drawcircle"
    ; xpos = r * cos(theta) + midx
    ; ypos = r * sin(theta) + midy

    draw_circle_loop:
        invoke Sleep,20
        ; xpos = r * cos(theta) + midx
        fld theta
        fcos
        fimul r
        fiadd midx
        fistp xpos

        ; ypos = r * sin(theta) + midy
        fld theta
        fsin
        fimul r
        fiadd midy
        fistp ypos

        invoke SetCursorPos,xpos,ypos

        fldpi
        fidiv ThetaInOneCircle
        fadd theta
        fstp theta

        fldpi
        fimul PiInOneCircle
        fcomp theta
        fnstsw status           ; Load from coprocessor to memory
        mov ax, status          ; Transfer memory to register
        sahf                    ; Transfer AH to flags register
    ja draw_circle_loop     ; Jump if PiInOneCircle(2) * Pi(3.141...) is "above" theta

    pop edi
    pop ebx

    ret

DrawCircle endp

; -------------------------------------------------------------------------

DrawSpiral proc near    ; BROKEN, NEED TO FIGURE OUT HOW TO INCREMENT R

    LOCAL rspiral :REAL10

    push ebx
    push edi

    fild r
    fstp rspiral
    mov theta, 0

    mov eax, maxx
    shr eax, 1
    mov midx, eax
   
    mov eax, maxy
    shr eax, 1
    mov midy, eax

    fld1
    fld rmod
    fdiv
    fld1
    fadd
    fstp rmod

    ; At this point, rspiral = 1, theta = 0, midx = maxx/2, midy = maxy/2
    ; Now, we want to draw our circle via the loop "drawcircle"
    ; xpos = rspiral * cos(theta) + midx
    ; ypos = rspiral * sin(theta) + midy

    draw_spiral_loop:
        invoke Sleep,20
        ; xpos = r * cos(theta) + midx
        fld theta
        fcos
        fld rspiral
        fmul
        fiadd midx
        fistp xpos

        ; ypos = r * sin(theta) + midy
        fld theta
        fsin
        fld rspiral
        fmul
        fiadd midy
        fistp ypos

        invoke SetCursorPos,xpos,ypos

        fldpi
        fidiv ThetaInOneCircle
        fadd theta
        fstp theta

        fld rmod
        fld rspiral
        fmul
        fstp rspiral

        ;fldpi
        ;fimul PiInOneCircle
        ;fcomp theta
        ;fnstsw status           ; Load from coprocessor to memory
        ;mov ax, status          ; Transfer memory to register
        ;sahf                    ; Transfer AH to flags register
    ;ja draw_spiral_loop     ; Jump if PiInOneCircle(2) * Pi(3.141...) is "above" theta
   
        fild midy
        fld rspiral
        fadd
        fild maxy
        fcompp
        fnstsw status
        mov ax, status
        sahf
    ja draw_spiral_loop

    pop edi
    pop ebx

    ret

DrawSpiral endp

; -------------------------------------------------------------------------

end start

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««


rsrc.rc

#include "\masm32\include\resource.h"

mouseprog DIALOGEX 0, 0, 159, 200
STYLE DS_3DLOOK | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
CAPTION "Mouse Movement"
FONT 8, "Tahoma"
{
   CONTROL "Mouse &Circle", 100, BUTTON, BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 7, 22, 146, 14
   CONTROL "Mouse &Spiral", 101, BUTTON, BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 7, 40, 146, 14
   CONTROL "&Quit", 200, BUTTON, BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 6, 180, 50, 14
   CONTROL "Radius?", 150, EDIT, ES_CENTER | ES_AUTOHSCROLL | WS_CHILD | WS_VISIBLE | WS_BORDER | WS_TABSTOP, 6, 5, 147, 13
}

cman

OK , thanks! I just want to graph a set of ordered pairs so that I can look at the results of some information graphically. Not looking to do anything fancy . Thank you! :bg