' This program example demonstrates the SPIN CONTROL i.e. an UP-DOWN CONTROL
' in conjunction with a buddy window. The program analyzes the statistical
' significance of the difference between two proportions. The input is made
' using 4 spin controls.
'
' The code skeleton was generated using EZGUI Freeware Dialog Designer
' by Christopher R. Boss. See web site at EZGUI.COM
' This ingenious freeware is highly recommended.
'
' For clarity unused code has been removed. Normally this is not
' necessary.
'
' Erik Christensen, Copenhagen, Denmark. ----- [email protected]"
Code:
#COMPILE EXE #REGISTER NONE #DIM ALL ' This is helpful to prevent errors in coding %NOANIMATE = 1 %NOBUTTON = 1 %NOCOMBO = 1 %NODRAGLIST = 1 %NOHEADER = 1 %NOIMAGELIST = 1 %NOLIST = 1 %NOTRACKBAR = 1 %MAX_SPIN = 16960 ' absolute maximum spin control input value %MIN_SPIN = 0 ' minimum spin control input value for this program #INCLUDE "win32api.inc" ' Must come first before other include files ! #INCLUDE "commctrl.inc" ' The Common Controls include file ! ' ************************************************************* ' Application Constants and Declares ' ************************************************************* %IDD_FORM1_LABEL_ABSENT = 100 %IDD_FORM1_LABEL_PRESENT = 105 %IDD_FORM1_LABELB = 110 %IDD_FORM1_LABELA = 115 %IDD_FORM1_UPDOWN_A_PRES = 120 %IDD_FORM1_UPDOWN_A_ABS = 125 %IDD_FORM1_UPDOWN_B_PRES = 130 %IDD_FORM1_UPDOWN_B_ABS = 135 %IDD_FORM1_BUTTON_COMPARE = 140 %IDD_FORM1_DESCRIBE = 145 %IDD_FORM1_TEXT_A_PRES = 150 %IDD_FORM1_TEXT_A_ABS = 155 %IDD_FORM1_TEXT_B_PRES = 160 %IDD_FORM1_TEXT_B_ABS = 165 %IDD_FORM1_TEXT_RESULTS = 170 %IDD_FORM1_BUTTON_EXIT = 175 ' -------------------------------------------------- DECLARE SUB ShowDialog_Form1(BYVAL hParent&) DECLARE CALLBACK FUNCTION Form1_DLGPROC DECLARE CALLBACK FUNCTION CBF_FORM1_BUTTON_COMPARE() DECLARE CALLBACK FUNCTION CBF_FORM1_BUTTON_EXIT() DECLARE FUNCTION PCHI2(BYVAL CHI2 AS DOUBLE, BYVAL F9 AS DOUBLE) AS DOUBLE GLOBAL hForm1& ' Dialog handle GLOBAL RESULT$ GLOBAL TT$ GLOBAL AnNo% FUNCTION PBMAIN LOCAL Count& LOCAL CC1 AS INIT_COMMON_CONTROLSEX ' from the "commctrl.inc" file: ' TYPE INIT_COMMON_CONTROLSEX ' dwSize AS LONG ' dwICC AS LONG ' END TYPE CC1.dwSize=SIZEOF(CC1) CC1.dwICC=%ICC_WIN95_CLASSES ' from the "commctrl.inc" file: ' DECLARE SUB InitCommonControlsEx LIB "COMCTL32.DLL" ALIAS _ ' "InitCommonControlsEx" (icc AS INIT_COMMON_CONTROLSEX) ' The InitCommonControlsEx function call ensures that the ' necessary common control dynamic-link library (DLL) is loaded. InitCommonControlsEX CC1 ShowDialog_Form1 0 DO DIALOG DOEVENTS TO Count& LOOP UNTIL Count&=0 END FUNCTION ' ************************************************************* ' Application Dialogs ' ************************************************************* SUB ShowDialog_Form1(BYVAL hParent&) LOCAL Style&, ExStyle&, T$,UDstyle&,BWstyle&,DWstyle& ' hParent& = 0 if no parent Dialog Style& = %WS_POPUP OR %DS_MODALFRAME OR %WS_CAPTION OR %WS_MINIMIZEBOX OR %WS_SYSMENU OR %DS_CENTER ExStyle& = 0 DIALOG NEW hParent&, "Comparison of 2 Proportions (or Percentages) Demonstrating the Spin Control", _ 0, 0, 308, 225, Style&, ExStyle& TO hForm1& CONTROL ADD LABEL, hForm1&, %IDD_FORM1_LABEL_ABSENT, "Characteristic absent", 22, 114, 66, 10 CONTROL ADD LABEL, hForm1&, %IDD_FORM1_LABEL_PRESENT, "Characteristic present", 22, 96, 66, 10 CONTROL ADD LABEL, hForm1&, %IDD_FORM1_LABELB, "Group 2", 168, 82, 60, 10 CONTROL ADD LABEL, hForm1&, %IDD_FORM1_LABELA, "Group 1", 98, 82, 60, 10 UDstyle& = %WS_CHILD OR %WS_VISIBLE OR %UDS_SETBUDDYINT OR %UDS_NOTHOUSANDS '%UDS_SETBUDDYINT Causes the up-down control to set the text of ' the buddy window when the position changes. ' The text consists of the position - formatted as ' a decimal string. '%UDS_NOTHOUSANDS Prevents insertion of a thousands separator between ' every three decimal digits. 'from the "commctrl.inc" file: '$UPDOWN_CLASS = "msctls_updown32" CONTROL ADD "msctls_updown32",hForm1&,%IDD_FORM1_UPDOWN_A_PRES,"",128,94,10,12,UDstyle& CONTROL ADD "msctls_updown32",hForm1&,%IDD_FORM1_UPDOWN_A_ABS,"",128,112,10,12,UDstyle& CONTROL ADD "msctls_updown32",hForm1&,%IDD_FORM1_UPDOWN_B_PRES,"",198,94,10,12,UDstyle& CONTROL ADD "msctls_updown32",hForm1&,%IDD_FORM1_UPDOWN_B_ABS,"",198,112,10,12,UDstyle& CONTROL ADD "Button", hForm1&,%IDD_FORM1_BUTTON_COMPARE,"Compare", 34, 128, 174, 12, _ %WS_CHILD OR %WS_VISIBLE OR %BS_PUSHBUTTON OR %WS_TABSTOP CALL CBF_FORM1_BUTTON_COMPARE T$="This program compares statistically two independent proportions using the "+ _ "Chi-square test."+$CRLF+" Example:"+$CRLF+"Group 1 has 110 females and 90 "+ _ "males. The proportion of females is 110/(110+90) = 0.55 or 55%."+$CRLF+ _ "Group 2 has 56 females and 68 males. The proportion of females is 56/(56+68) = "+ _ "0.45 or 45%."+$CRLF+" Is this difference random, or is it statistically "+ _ "significant? This you can determine by calculating the P-value"+ _ " (the probability that this difference can be explained by random factors alone). "+ _ "If the P-value is small say less than 0.05 or 5%, "+ _ "then the difference is said to be statistically significant."+$CRLF+ _ " This program calculates the difference between the proportions (with 95% "+ _ "confidence limits) and the P-value."+ _ " It also demonstrates the spin control i.e. an up-down control in conjunction with "+ _ "a buddy window."+$CRLF+" The test is approximate, especially for small groups. "+ _ $CRLF+" You can perform the test many times with different numbers. The latest "+ _ "result will always be on the top "+ _ "of the window and immediately visible. The previous results will still be present "+ _ "in the window. You can scroll down to them at any time."+$CRLF+ _ " Erik Christensen, Copenhagen, Denmark. [email protected]" DWstyle& = %WS_CHILD OR %WS_VISIBLE OR %ES_MULTILINE OR %WS_VSCROLL OR %ES_READONLY OR %ES_LEFT CONTROL ADD TEXTBOX, hForm1&,%IDD_FORM1_DESCRIBE,T$,2,0,306,80,DWstyle&,%WS_EX_CLIENTEDGE BWstyle& = %WS_CHILD OR %WS_VISIBLE OR %ES_MULTILINE OR %ES_RIGHT OR %ES_AUTOHSCROLL OR %WS_TABSTOP CONTROL ADD TEXTBOX, hForm1&, %IDD_FORM1_TEXT_A_PRES, "", 90, 94, 38, 12,BWstyle&,%WS_EX_CLIENTEDGE CONTROL ADD TEXTBOX, hForm1&, %IDD_FORM1_TEXT_A_ABS, "", 90, 112, 38, 12,BWstyle&,%WS_EX_CLIENTEDGE CONTROL ADD TEXTBOX, hForm1&, %IDD_FORM1_TEXT_B_PRES, "", 160, 94, 38, 12,BWstyle&,%WS_EX_CLIENTEDGE CONTROL ADD TEXTBOX, hForm1&, %IDD_FORM1_TEXT_B_ABS, "", 160, 112, 38, 12,BWstyle&,%WS_EX_CLIENTEDGE CONTROL SEND hForm1&, %IDD_FORM1_UPDOWN_A_PRES, %UDM_SETBUDDY, _ GetDlgItem(hForm1&, %IDD_FORM1_TEXT_A_PRES), 0& 'The %UDM_SETBUDDY message sets the buddy window for an up-down control. 'Thus the up-down control and its associated byddy edit window act 'together as a unity. This is taken care of by Windows. CONTROL SEND hForm1&, %IDD_FORM1_UPDOWN_A_PRES, _ %UDM_SETRANGE, 0&, MAKLNG(%MAX_SPIN, %MIN_SPIN) 'The %UDM_SETRANGE message sets the minimum and maximum 'positions (range) for an up-down control. CONTROL SEND hForm1&, %IDD_FORM1_UPDOWN_A_ABS, %UDM_SETBUDDY, _ GetDlgItem(hForm1&, %IDD_FORM1_TEXT_A_ABS), 0& CONTROL SEND hForm1&, %IDD_FORM1_UPDOWN_A_ABS, _ %UDM_SETRANGE, 0&, MAKLNG(%MAX_SPIN, %MIN_SPIN) CONTROL SEND hForm1&, %IDD_FORM1_UPDOWN_B_PRES, %UDM_SETBUDDY, _ GetDlgItem(hForm1&, %IDD_FORM1_TEXT_B_PRES), 0& CONTROL SEND hForm1&, %IDD_FORM1_UPDOWN_B_PRES, _ %UDM_SETRANGE, 0&, MAKLNG(%MAX_SPIN, %MIN_SPIN) CONTROL SEND hForm1&, %IDD_FORM1_UPDOWN_B_ABS, %UDM_SETBUDDY, _ GetDlgItem(hForm1&, %IDD_FORM1_TEXT_B_ABS), 0& CONTROL SEND hForm1&, %IDD_FORM1_UPDOWN_B_ABS, _ %UDM_SETRANGE, 0&, MAKLNG(%MAX_SPIN, %MIN_SPIN) CONTROL ADD TEXTBOX, hForm1&,%IDD_FORM1_TEXT_RESULTS,"",2,144,306,80, _ %WS_CHILD OR %WS_VISIBLE OR %ES_MULTILINE OR %ES_READONLY OR _ %ES_LEFT OR %ES_AUTOVSCROLL OR %WS_VSCROLL, _ %WS_EX_CLIENTEDGE CONTROL ADD "Button", hForm1&,%IDD_FORM1_BUTTON_EXIT,"Exit",238,128,44,12, _ %WS_CHILD OR %WS_VISIBLE OR %BS_PUSHBUTTON OR %WS_TABSTOP _ CALL CBF_FORM1_BUTTON_EXIT DIALOG SHOW MODELESS hForm1& , CALL Form1_DLGPROC END SUB ' ************************************************************* ' Dialog Callback Procedure ' for Form Form1 ' uses Global Handle - hForm1& ' ************************************************************* CALLBACK FUNCTION Form1_DLGPROC ' not used END FUNCTION CALLBACK FUNCTION CBF_FORM1_BUTTON_COMPARE LOCAL A$,B$,C$,D$ LOCAL AA%,BB%,CC%,DD% IF CBCTLMSG=%BN_CLICKED THEN CONTROL GET TEXT hFORM1&, %IDD_FORM1_TEXT_A_PRES TO A$ CONTROL GET TEXT hFORM1&, %IDD_FORM1_TEXT_A_ABS TO B$ CONTROL GET TEXT hFORM1&, %IDD_FORM1_TEXT_B_PRES TO C$ CONTROL GET TEXT hFORM1&, %IDD_FORM1_TEXT_B_ABS TO D$ AA%=VAL(A$): BB%=VAL(B$): CC%=VAL(C$): DD%=VAL(D$) IF (AA%>0 AND DD%>0) OR (BB%>0 AND CC%>0) THEN RESULT$="" CALL CALCULATE(AA%,BB%,CC%,DD%,RESULT$) TT$=RESULT$+TT$ CONTROL SET TEXT hForm1&, %IDD_FORM1_TEXT_RESULTS,TT$ ELSE MSGBOX "Too many cells are zero. Cannot perform calculation.", _ %MB_ICONHAND,"Problem:" END IF END IF END FUNCTION CALLBACK FUNCTION CBF_FORM1_BUTTON_EXIT DIALOG END hForm1& END FUNCTION ' ------------------------------------------------ SUB CALCULATE(A%,B%,C%,D%,T$) ' For a reference to the method see standard statistical textbooks ' e.g. Armitage P & Berry G. Statistical Methods in Medical Research, ' Blackwell, Oxford, 1994. LOCAL TN1 AS SINGLE, _ TN2 AS SINGLE, _ TNN AS SINGLE, _ P1 AS SINGLE, _ P2 AS SINGLE, _ PS AS SINGLE, _ SED AS SINGLE, _ DIF AS SINGLE, _ AB AS SINGLE, _ AC AS SINGLE, _ DB AS SINGLE, _ DC AS SINGLE, _ CHI2 AS DOUBLE, _ NS AS SINGLE, _ OS AS SINGLE, _ P AS DOUBLE INCR AnNo TN1=A%+B% TN2=C%+D% TNN=TN1+TN2 P1=A%/TN1 P2=C%/TN2 T$=T$+" Analysis number:"+STR$(AnNo)+$CRLF T$=T$ + " Group 1: Proportion with characteristic (P1):" _ +STR$(A%)+" /"+STR$(TN1)+" ="+FORMAT$(P1*100,"###.##")+"%"+$CRLF T$=T$ + " Group 2: Proportion with characteristic (P2):" _ +STR$(C%)+" /"+STR$(TN2)+" ="+FORMAT$(P2*100,"###.##")+"%"+$CRLF PS=(A%+C%)/(TN1+TN2) SED=SQR(PS*(1-PS)*(1/TN1+1/TN2)) DIF=A%/TN1-C%/TN2 T$=T$ + " Difference between proportions (P1 - P2) =" _ +FORMAT$(DIF*100,"###.##")+"%"+$CRLF NS=DIF*100-1.96*SED*100 IF NS<-100 THEN NS=-100 OS=DIF*100+1.96*SED*100 IF OS>100 THEN OS=100 T$=T$ + " 95% Confidence interval of difference: ("+FORMAT$(NS,"###.##") _ +" , "+FORMAT$(OS,"###.##")+")"+$CRLF AB=A%+B% AC=A%+C% DB=D%+B% DC=D%+C% TNN=AB+DC ' CHI2=TNN*(ABS(A%*D%-B%*C%)-TNN/2)^2/(AB*DC*AC*DB) ' with Yates's corrrection CHI2=TNN*(ABS(A%*D%-B%*C%))^2/(AB*DC*AC*DB) ' without Yates's correction T$=T$+ " Chi-square ="+ FORMAT$(CHI2,"####.###")+" P-value =" P=PCHI2(CHI2,1) T$=T$+FORMAT$(P,"##.######")+$CRLF '+$CRLF IF P<0.05 THEN T$=T$+" The difference is statistically significant." ELSE T$=T$+" The difference is not statistically significant and probably random." END IF T$=T$+$CRLF+$CRLF END SUB ' ************************************************************* FUNCTION PCHI2(BYVAL X AS DOUBLE, BYVAL F AS DOUBLE) AS DOUBLE ' FUNCTION PCHI2 - CALCULATES THE P-VALUE FROM ' THE CHI-SQUARE VALUE AND THE DEGREES OF FREEDOM (BEING 1 IN THIS PROGRAM) ' The probability is calculated using series expansions 26.4.4 and 26.4.5 ' in: Handbook of mathematical Functions. Editors: Abramowitz M & Stegun IA, ' Dover, New York, 1972. The function looks awful, but it does the job. LOCAL D#,E#,R#,G#,H#,SL#,S#,T#,P#,C#,SK#,Q# Q# = 1 IF X>30 AND F=1 THEN Q=0: GOTO 4255 ' added to prevent overflow problems IF X = 0 OR F = 0 THEN GOTO 4255 D# = F: E# = D# / 2: R# = F - INT(F / 2) * 2 G# = 1 IF R# > .3 THEN GOTO 4205 4190 E# = E# - 1 IF E# < 1.8 THEN GOTO 4225 G# = G# * E#: GOTO 4190 4205 G# = SQR(ATN(1) * 4) ' = PI 4210 E# = E# - 1 IF E# < .3 THEN GOTO 4225 G# = G# * E#: GOTO 4210 4225 H# = ((X / 2) ^ (D# / 2) * EXP(-X / 2)) / (X * G#) SL# = H# * 2 * X / D#: S# = 0: T# = 0: P# = 1 4230 D# = D# + 2: P# = P# * X / D#: S# = S# + P#: C# = ABS(S# - T#) IF C# < .0000000001# THEN GOTO 4245 T# = S#: GOTO 4230 4245 SK# = (S# + 1) * SL#: Q# = 1 - SK# IF Q# < .0000000001# THEN Q# = .0000000001# 4255 FUNCTION = Q# END FUNCTION
[This message has been edited by Erik Christensen (edited June 30, 2005).]
Comment